承诺的方法什么时候被实现或拒绝?

时间:2015-11-07 16:07:36

标签: javascript asynchronous promise bluebird

promises上的then()方法返回一个promise。承诺可以处于三种状态之一,待决,履行或拒绝。但是,在创建承诺时,如果您希望履行或拒绝承诺,则可以使用已解决和拒绝的方法进行调用。我无法在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()返回一个promise。现在,这个控制台将打印三个两个。一旦调用异步,就会调用第二个then语句。有没有办法在我通知它已解决之前没有调用第二个语句。

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

3 个答案:

答案 0 :(得分:2)

所以会发生什么,findUser得到满足(并且没有被拒绝),因此.then()的第一个参数中的回调会调用(而不是第二个)。 在.then()子句中,您console.log("ONE")并且您没有返回任何内容(因为您属于else {子句,并且您只返回到createHash的回调在承诺的背景下意义重大。),所以它实际上返回undefined

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

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

正确的方法是编写User.generateHash以便它也返回一个promise,然后你可以将它与promise链的其余部分链接起来,而不必处理promise promise回调中的异步内容。

答案 1 :(得分:1)

  

创建承诺时,如果您希望履行或拒绝承诺,则可以使用已解决和拒绝的方法进行调用。我无法在then()方法

中找到如何在函数上使用这些方法

在承诺上使用then方法时,您无权访问resolve / reject回调 - then为您管理所有这些。它确实返回了新的promise,它将使用回调的 result 解析,即其返回值。此返回值可以是将自动同化的承诺(当您使用承诺解决时,它将自动履行/拒绝承诺的结果)。

所以这就是你需要做的。如果要在then回调中调用回调方法,则必须为其创建承诺,然后可以return。最简单,最好的方法是事先promisify the callback function,但您也可以使用Promise构造函数(您可以访问resolve / reject)。< / p>

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

答案 2 :(得分:0)

如果done()和User.generateHash()没有返回promises,那么在进入下一个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);
});

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