【问题标题】:Asynchronous call inside a promisePromise 中的异步调用
【发布时间】:2017-08-24 20:13:56
【问题描述】:

首先我知道这个问题已经被问过很多次了,但我不知道该怎么做。 我是 Node.js 的新手,正在处理它的异步方面。

这是我的代码

passport.use(new LocalStrategy({ usernameField: 'email', passwordField: 'password' }, function (email, pass, done) {   
    Users.query(email).exec(function (err, item) {
        const message = 'Login Invalid';
        if (err) return done(err);

        var promise = GetHash({ item, pass });        
        promise.then((data) => {                        
            return done(null, data)
        }).catch((err) => {
            console.log(err);
            return done(null, false, { message });
        });                             
    });    
}));

function GetHash(userPasswordRequest) {
    return new Promise(function (resolve, reject) {
        if (userPasswordRequest.item && userPasswordRequest.item.Items[0]) {
            var userRecord = userPasswordRequest.item.Items[0].attrs;
            if (userRecord.old) {
                if (crypto.createHash('sha256').update(userPasswordRequest.pass, 'ucs-2').digest('base64') === userRecord.password) {
                    var newHash = bcrypt.hashSync(userPasswordRequest.pass, 10);
                    Users.update({ email: userRecord.email, password: newHash, old: null }, function (err, newItem) {
                        if (err) { console.log(err); } else {
                            console.log('first call');
                            resolve(newItem.attrs);
                        }
                    });                
                }
            }
            else {
                if (bcrypt.compareSync(userPasswordRequest.pass, userRecord.password)) {
                    console.log('first call');
                    resolve(userPasswordRequest.item.Items[0].attrs);                    
                }
            }
        }
        reject();
    })
}

问题在这里:

 if (crypto.createHash('sha256').update(userPasswordRequest.pass, 'ucs-2').digest('base64') === userRecord.password) {
                    var newHash = bcrypt.hashSync(userPasswordRequest.pass, 10);
                    Users.update({ email: userRecord.email, password: newHash, old: null }, function (err, newItem) {
                        if (err) { console.log(err); } else {
                            console.log('first call');
                            resolve(newItem.attrs);
                        }
                    });                
                }

因为Users.update 是异步的,我在解决它之前拒绝了承诺。

我尝试了很多东西,承诺中的承诺和许多其他东西,但我无法使这个工作正常。

任何帮助将不胜感激

【问题讨论】:

  • 你不会把所有东西都放在一个巨大的 Promise 中,而是将它拆分成一个 Promise 链。因此,首先获取用户,然后将其作为两个单独的操作进行加密。如果链的任何部分发生故障,它会中止链并允许您在整个链中的一个位置捕获错误。
  • 听起来您只是在reject() 调用前面缺少了一个else
  • 你在使用特定的 promise 库吗?
  • @Bergi 我正在使用来自 Node.js 4.x 的内置承诺
  • @Theo Btw, dynamodb appears to already return promises - 所以你根本不需要任何new Promise

标签: javascript node.js asynchronous promise amazon-dynamodb


【解决方案1】:

您不应该使用reject 作为替代,而是在发生错误情况时显式调用。

像这样:

if (userPasswordRequest.item && userPasswordRequest.item.Items[0]) {
  ...
} else {
  return reject(Error('invalid userPasswordRequest'));
}

还有:

if (bcrypt.compareSync(userPasswordRequest.pass, userRecord.password)) {
  console.log('first call');
  return resolve(userPasswordRequest.item.Items[0].attrs);                    
} else { 
  return reject(Error('invalid password'));
}

这也不对:

if (err) { console.log(err); }

不要只记录错误,用它来拒绝承诺:

if (err) {
  console.log(err);
  return reject(err);
}

如您所见,解决或拒绝后返回也是不错的形式。

【讨论】:

  • 好的,我知道我可以在任何地方使用 else,但我认为存在更好的解决方案
  • @Theo 更好的解决方案是正确使用承诺并分别承诺每个异步函数:-)
  • @Bergi 是的!这是我尝试过的。承诺其他功能(特别是对数据库的调用),但我无法使其工作
  • @Theo 不,我的意思是你自己的函数不应该调用Promise 构造函数。如果您使用它们的异步变体,您应该只使用它来包装 Users.query(…).execUsers.update 和加密函数。围绕丑陋的回调构建一个外观,然后仅使用带有 then 的纯 Promise。
猜你喜欢
  • 2019-06-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-02-08
  • 2019-05-16
  • 1970-01-01
  • 1970-01-01
  • 2018-01-14
相关资源
最近更新 更多