Promise.resolve returns Undefined

2019-08-23 09:48发布

问题:

This is a continuation of Multiple Promises - Where to resolve? where I use the same code for different function.

However, this time the Promise.resolve is returning undefined.

Results Thanks to multiple people pointing out the mistakes. There are multiple errors in the code which I realised I committed.

1) Using && in a non Boolean operation.

should use

(console.log(results) , Promise.resolve(results)

instead of

console.log(results) && Promise.resolve(results)

2) Using unneeded Promise.resolve - just return the results from the Async function will yield the same result as using Promise.resolve.

My final codes.

getMessages: function (roomId) {

    return keysAsync('room:'+roomId)
    .then(room => 
        room === '' ? Promise.reject('Invalid room Id')
                    : smembersAsync('room:messages:'+roomId))
        .then(messagesId => { return messagesId })
        .catch(err => { return err }))

}

Original Question I'm using nodejs promisify so I have the followings declared as promise for Redis

const { promisify } = require('util');
const getAsync = promisify(client.get).bind(client);
const hmsetAsync = promisify(client.hmset).bind(client);
const hsetAsync = promisify(client.hset).bind(client);
const incrAsync = promisify(client.incr).bind(client);
const smembersAsync = promisify(client.smembers).bind(client);
const keysAsync = promisify(client.keys).bind(client);
const sismemberAsync = promisify(client.sismember).bind(client);

getMessages: function (roomId) {

    return keysAsync('room:'+roomId)
    .then(room => 
        room === '' ? Promise.reject('Invalid room Id')
                    : smembersAsync('room:messages:'+roomId))
        .then(messagesId => console.log(messagesId) && Promise.resolve(messagesId))
        .catch(err => Promise.reject(err))

},

And then i call the function as follows

tools.getMessages('4').then((results) => {
    console.log('Messages in Room 4 => ', results);
  }).catch(err => console.log(err))

In my console, I can see the following results

[ '191', '192', '193', '194', '195', '196', '197',
'198', '199', '200', '201', '202', '207', '208', '209', '210', '211', '212', '213', '214', '215', '216', '217', '218' ] //this is when i console log messagesId

Messages in Room 4 => undefined //This is when i console log results

回答1:

console.log() returns undefined, which is falsey. && is a short-circuiting operator, and only evaluates the second expression when the first expression is truthy. So it's never executing Promise.resolve(messagesId).

Instead of &&, use the comma operator. It evaluates both of its expressions and returns the second one.

    .then(messagesId => (console.log(messagesId), Promise.resolve(messagesId)))


回答2:

As has already been explained, you are getting the return value of console.log(messagesId) as your resolved value which is undefined because of the way the && works and what console.log() returns.

But since, all you're really trying to do here is log the result and continue with the same resolved value, I'd suggest a cleaner way of doing that is to make yourself a little utility function:

function log(arg) {
    console.log(arg);
    return arg;
}

Then, you can change this:

.then(messagesId => console.log(messagesId) && Promise.resolve(messagesId))

to this:

.then(log)

Notice that within a .then() handler any plain value you return will become the resolved value of the promise chain. You can also return a promise if you want to add another async operation into the promise chain, but if you already have a value, you can just return value;. You don't need to return Promise.resolve(value);. Inside a .then() handler, the Promise.resolve() is just extra, unnecessary code - just return the value directly.



回答3:

The Promise doesn't resolve with messageId, because console.log() returns undefined:

console.log(Boolean(console.log("test")));

But this is not the only thing that you should change, in fact, you can leave out a lot, because the smembersAsync() function returns a promise, that you can simply return:

instead of

return keysAsync('room:'+roomId)
    .then(room => 
        room === '' ? Promise.reject('Invalid room Id')
                    : smembersAsync('room:messages:'+roomId))
        .then(messagesId => console.log(messagesId) && Promise.resolve(messagesId))
        .catch(err => Promise.reject(err))

simply use

return keysAsync('room:'+roomId)
    .then(room => {
        if (room === "") { Promise.reject('Invalid room Id') } 
        else return smembersAsync('room:messages:'+roomId)
    })