Javascript链式承诺

时间:2016-10-31 13:17:35

标签: javascript ajax promise chained

我有3个ajax调用,我在演示代码中使用setTimeout函数进行模拟。我将从一段工作正常的代码开始:所有调用都是并行进行的,我希望所有的都能成功,否则就会出错。

var p1 = function () {
    return new Promise(function (resolve, reject) {
        setTimeout(function () {
            console.log('p1');
            resolve(1);
            //reject(1);
        }, 2000);
    });
};

var p2 = function () {
    return new Promise(function (resolve, reject) {
        setTimeout(function () {
            console.log('p2');
            resolve(2);
            //reject(2);
        }, 1000);
    });
};

var p3 = function () {
    return new Promise(function (resolve, reject) {
        setTimeout(function () {
            console.log('p3');
            resolve(3);
            //reject(3);
        }, 5000);
    });
};

Promise.all([p1(), p2(), p3()])
.then(values => {
    console.log(values);
}).catch(values => {
    console.log("error: " + values);
});

现在,重要的变化是p2只有在p1成功结束后才能执行,而不是其他情况。这是新的代码,但这个并不是所有的代码:

var p1 = function () {
    return new Promise(function (resolve, reject) {
        setTimeout(function () {
            console.log('p1');
            resolve(1);
            //reject(1);
        }, 2000);
    });
};

var p2 = function () {
    return new Promise(function (resolve, reject) {
        setTimeout(function () {
            console.log('p2');
            resolve(2);
            //reject(2);
        }, 1000);
    });
};

var p21 = function() {
    return new Promise(function (resolve, reject) {
        p1().then(function (data) { p2(); })
    });
};

var p3 = function () {
    return new Promise(function (resolve, reject) {
        setTimeout(function () {
            console.log('p3');
            resolve(3);
            //reject(3);
        }, 5000);
    });
};

Promise.all([p21(), p3()])
.then(values => {
    console.log(values);
}).catch(values => {
    console.log("error: " + values);
});

我已经阅读了有关如何处理JS承诺的各种教程,我仍然无法解决我的问题。

请注意,测试函数中使用的时间延迟只是一个示例,代码应该无论函数的相对持续时间如何都可以工作(即每个函数的天气更慢或更快)。

2 个答案:

答案 0 :(得分:0)

您可以通过在前一个promise的next()函数中返回下一个promise调用来使promises同步。这听起来很复杂,但很简单:

/*
* Remains the very same
*/

var p1 = function () {
    return new Promise(function (resolve, reject) {
        setTimeout(function () {
            console.log('p1');
            resolve(1);
            //reject(1);
        }, 2000);
    });
};

var p2 = function () {
    return new Promise(function (resolve, reject) {
        setTimeout(function () {
            console.log('p2');
            resolve(2);
            //reject(2);
        }, 1000);
    });
};

var p3 = function () {
    return new Promise(function (resolve, reject) {
        setTimeout(function () {
            console.log('p3');
            resolve(3);
            //reject(3);
        }, 5000);
    });
};

// If you want to run p1 and p3 in "parallel" + after p1 is finished run p2
Promise.all([p1().then(valuesFromP1 => {
    return p2();
}), p3()]).then(values => {
    // all 3 finished
})


// Or alternatively something similar but slightly different - see the comments
Promise.all([p1().then(valuesFromP1 => {
         // handle p1 is done
         p2().then(valuesFromP2 => {
            // handle p2 is done
         });
     }), p3()])
     .then(values => {
         // handle p1 and p3 are done but you don't care about p2
     });


// Or if you don't care about common finish you can simply do this
p1().then(valuesFromP1 => {
     // handle p1 is done
     p2().then(valuesFromP2 => {
        // handle p2 is done
     });
});
p3().then(valuesFromP3 => {
     // handle p3 is done
});

答案 1 :(得分:0)

我相信你的第二个代码集中缺少的是返回结果。你的内心承诺不仅没有“返回p2”,而且你没有使用你正在生成的解析/拒绝功能。对于初学者,我会避免创建新的Promise对象作为解析其他对象的方法 - 通常,这可以通过更好地理解promise库(使用thenall)来完成。

// this function returns a 2-long array (inside a promise), so you may want to change
// the calling syntax
var p21 = function() {
    // Do not "return promise" - we create a new one just by calling "then()"
    //return new Promise(function (resolve, reject) {
    return p1().then(function (data) {
        return p2().then(function(data2) {
            return [data, data2];
        });
    });
};