多重承诺 - 在哪里解决? [英] Multiple Promises - Where to resolve?

查看:54
本文介绍了多重承诺 - 在哪里解决?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我刚开始承诺.

我正在使用 nodejs promisify,所以我将以下内容声明为 Redis 的承诺

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);

我有以下功能,但我不知道放置解析(消息)的正确位置

I have the following function and I do not know where is the right place to put the resolve(message)

function sendMessage(senderId = '', roomId = '', text = '', type='text') {

        var message = {}
        return new Promise( function (resolve, reject) {

    if (senderId == '') {
        reject('Invalid Characters in Sender Id or Sender Id is empty.');
    }


    if (roomId == '') {
        reject('Invalid Characters in Room Id or Room Id is empty.');
    }

    if (text == '') {
        console.log('Text:' ,text);
        reject('Invalid Characters in Text or Text is empty.');
    }
            //Check if Room Exist

            keysAsync('room-'+roomId).then((value) => {

                value == '' && reject('Room '+roomId+ ' does not exist.');
                sismemberAsync('roomuser-'+roomId, senderId).then((ismember)=> {
                    ismember == 0 && reject('User ' + senderId + ' is not a member of room ' + roomId);

                    const datetime = new Date();
                    incrAsync('messageId')
                    .then((id) => {
                        //Create the message Hash
                        hmsetAsync('messsage:'+id, 'id', id, 'roomId', roomId, 'senderId', senderId, "created", datetime, "text", text);
                        //add message to Set
                        saddAsync('roommessages-'+roomId, id);

                        message = { id: id, roomId: roomId, senderId: senderId, created: datetime, text: text }
                        resolve(message) //If i place here i don't get the resolve.

                    }).catch(err => reject(err))

                }).catch(err => reject(err))

            }).catch(err => reject(err))
        })
    }

然后我试着像这样调用这个函数

And then I tried to call the function like this

tools.sendMessage(3, 4, 'Does this work?','text').then((result)=> {
  console.log('Send Message Result => ',result);
}).catch(err => { 
  console.log(err)
});

如果我把resolve(message)放在现在的位置,上面的promise不会解析,send Message result"也不会显示.

If I were to place the resolve(message) at where it is now, the above promise doesn't resolve, and "send Message result" doesn't show at all.

如果我把它放在更远的承诺链之外,var 消息将返回一个空对象 {}

If i place it further out of the chain promise, the var message returns a empty object {}

我的问题:我应该将解析放置在需要多次 Promise 调用的此类函数中,因为我需要等待多次 redis 检查?

My question: Where should I place the resolve in this kind of functions where I require multiple promise calls since I need to wait for multiple redis checks?

我有很多功能需要在我进行下一步操作之前完成所有 redis 调用.

I have many functions that requires all my redis calls to be made before I can carry on to next action.

推荐答案

我可能会考虑如下重构您的代码.如果您需要在中间 .then() 阶段捕获错误,请使用 onrejected 回调.

I might consider refactoring your code as follows. If you need to catch errors at interim .then() stages then use onrejected callbacks.

function sendMessage(senderId = '', roomId = '', text = '', type='text') {
  return keysAsync('room-'+roomId)
         .then(value => value === '' ? Promise.reject('Room '+roomId+ ' does not exist.')
                                     : sismemberAsync('roomuser-'+roomId, senderId))
         .then(ismember => ismember === 0 ? Promise.reject('User ' + senderId + ' is not a member of room ' + roomId)
                                          : incrAsync('messageId'))
         .then(id => { var datetime =new Date();
                       hmsetAsync('messsage:'+id, 'id', id, 'roomId', roomId, 'senderId', senderId, "created", datetime, "text", text);
                       saddAsync('roommessages-'+roomId, id);
                       return { id: id, roomId: roomId, senderId: senderId, created: datetime, text: text };
                     })
         .then(message => doSomethingWith(message))
         .catch(errorHandler);
}

在上面的代码中,我将 new Date() 移动到实际使用它的下面一个阶段,但是如果出于某种原因您需要在原始 datetime>.then() 阶段如您的问题所示,那么您也可以执行以下操作;

In the above code i moved the new Date() to one stage below where it is actually used however if for some reason you need datetime at the original .then() stage as shown in your question then you may as well do as follows;

function sendMessage(senderId = '', roomId = '', text = '', type='text') {
  return keysAsync('room-'+roomId)
         .then(value => value === '' ? Promise.reject('Room '+roomId+ ' does not exist.')
                                     : sismemberAsync('roomuser-'+roomId, senderId))
         .then(ismember => ismember === 0 ? Promise.reject('User ' + senderId + ' is not a member of room ' + roomId)
                                          : Promise.all([incrAsync('messageId'), new Date()]))
         .then(([id, datetime]) => { hmsetAsync('messsage:'+id, 'id', id, 'roomId', roomId, 'senderId', senderId, "created", datetime, "text", text);
                                     saddAsync('roommessages-'+roomId, id);
                                     return { id: id, roomId: roomId, senderId: senderId, created: datetime, text: text };
                                   })
         .then(message => doSomethingWith(message))
         .catch(errorHandler);
}

这篇关于多重承诺 - 在哪里解决?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆