promise 的 then 方法什么时候会被 fulfilled 或 rejected?

When does a promise's then method become fulfilled or rejected?

承诺 returns 承诺的 then() 方法。 Promise 可以处于三种状态之一:pending、fulfilled 或 rejected。然而,当你创建一个承诺时,你有一个 resolved 和 rejected 方法可以在你希望你的承诺被履行或拒绝时调用。我找不到如何在 then() 方法中的函数上使用这些方法。当我尝试在 then() 链的中间使用带有回调的普通异步函数时,这给我带来了问题。以此代码为例。

        User.findOne({
            where: {
                email: email
            }
        }).then(function(user){
            if(user){
                return done(null, false, req.flash('signupMessage', 'That email is already taken.'));
            }else{
                var user = User.build({ email: email });
                console.log("ONE");
                User.generateHash(password, function(err, hash){
                    console.log("TWO");
                    if(err){
                        return done(err);
                    }else{
                        user.password = hash;
                        var newUser = user.save();
                        return newUser;
                    }
                })
            }
        }, function(err){
            console.log("ERROR: ", err);
        }).then(function(newUser){
            console.log("THREE");
            return done(null, newUser);
        }, function(err){
            console.log("USER NOT CREATED: ", err);
        });

在这种情况下 User.findOne() returns 一个承诺。现在控制台将打印一三二。一旦调用异步,就会调用第二个 then 语句。有没有办法在我通知它已解决之前不调用第二个 then 语句。

(我知道这将是修复几种不同方法的简单代码,我更好奇为什么以及何时实现第一个语句返回的 then 承诺。)

所以发生的事情是,findUser 得到满足(而不是被拒绝),因此 .then() 的第一个参数中的回调调用(而不是第二个)。 在 .then() 子句中,你 console.log("ONE") 而你没有 return 任何东西(因为你落入 else { 子句,而你只在回调中 return到 createHash 这在承诺的上下文中意义不大。),所以它实际上 returns undefined.

然后下一个 .then() 调用,你得到 console.log("THREE").

然后在将来的某个时候,您会调用 createHash 的回调,然后您会得到 console.log("TWO").

正确的方法应该是写 User.generateHash 这样它也 return 是一个承诺,然后你可以将它与承诺链的其余部分链接起来,而不必处理异步你的承诺回调中的东西。

如果 done() 和 User.generateHash() 没有 return 承诺,那么该程序的第二级没有理由在进入下一个 then() 块之前等待。

要解决此问题,或者要查看您的打印语句打印出一二三,我会这样做

User.findOne({
    where: {
        email: email
    }
}).then(function(user){
    var promise;
    if(user){
        promise = done(null, false, req.flash('signupMessage', 'That email is already taken.'));
    }else{
        var user = User.build({ email: email });
        console.log("ONE");
        promise = User.generateHash(password, function(err, hash){
            return new Promise(function(resolve, reject){
                console.log("TWO");
                if(err){
                    reject(done(err));
                }else{
                    user.password = hash;
                    var newUser = user.save();
                    resolve(newUser);
                }
            });
        });
    }

    return promise;
}, function(err){
    console.log("ERROR: ", err);
}).then(function(newUser){
    console.log("THREE");
    return done(null, newUser);
}, function(err){
    console.log("USER NOT CREATED: ", err);
});

这样第一个 then 将在进入下一个 then 块之前等待 promise 被解析,这意味着 User.generateHash 必须在进入下一个 then 块之前解析,因为变量 promise 依赖于它.

When creating a promise you have a resolved and rejected method to call when you want your promise to be fulfilled or rejected. I can not find out how to use these methods on functions in the then() method

在承诺中使用 then 方法时,您无权访问 resolve/reject 回调 - then 为您管理所有这些。它执行 return 新承诺,该承诺将通过回调的 结果 解决,即它的 return 值 .这个 return 值可以是一个将被自动同化的承诺(当你用一个承诺解决时,它会自动 fulfill/reject 与那个承诺的结果)。

这就是您需要在此处执行的操作。当您想在 then 回调中调用回调方法时,您必须为其创建一个承诺,然后您可以 return。最简单和最好的方法是事先使用 promisify the callback function,但您也可以使用 Promise 构造函数(您可以在其中访问 resolve/reject)。

    User.findOne({
        where: {
            email: email
        }
    }).then(function(user){
        if (user){
            throw new Error('That email is already taken.');
        } else {
            var user = User.build({ email: email });
            console.log("ONE");
            var promise = new Promise(function(resolve, reject) {
//                        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
                User.generateHash(password, function(err, hash){
                if (err) reject(err);
                else     resolve(hash);
            });
            return promise.then(function(hash) {
                console.log("TWO");
                user.password = hash;
                var newUser = user.save();
                return newUser;
            });
        }
    }).then(function(newUser){
        console.log("THREE");
        return done(null, newUser);
    }, function(err){
        console.log("ERROR: ", err);
        return done(null, false, req.flash('signupMessage', err.message));
    });