使用promises运行异步函数

mad*_*ox2 4 javascript promise ecmascript-6 es6-promise

我试图使用promises串行运行多个异步任务.每个任务应在上一个任务完成后立即运行.这是我尝试的简化示例:

var order = [];
var tasks = [
    new Promise(resolve => {
        order.push(1);
        setTimeout(() => {
            order.push(2)
            resolve();
        }, 100);
    }),
    new Promise(resolve => {
        order.push(3);
        setTimeout(() => {
            order.push(4)
            resolve();
        }, 100);
    }),
    new Promise(resolve => {
        order.push(5);
        resolve();
    })
];

tasks.reduce((cur, next) => cur.then(next), Promise.resolve()).then(() => {
    console.log(order); // [ 1, 3, 5 ]
});
setTimeout(() => console.log(order), 200); // [ 1, 3, 5, 2, 4 ]
Run Code Online (Sandbox Code Playgroud)

我希望在回调函数中order是相同[ 1, 2, 3, 4, 5 ]的.但是我得到了那些奇怪的结果([ 1, 3, 5 ]then回调和[ 1, 3, 5, 2, 4 ]延迟功能中).我错过了什么?

ade*_*neo 5

当你写的东西像

new Promise(resolve => {
    order.push(1);
    setTimeout(() => {
        order.push(2)
        resolve();
    }, 100);
});
Run Code Online (Sandbox Code Playgroud)

它立即执行,意味着它现在运行,并在0.1秒内解决.
不要紧,你写一个数组里面,功能仍然跑了,现在,并承诺返回的数组中的值.

换句话说,所有三个promise呼叫都是并行运行的,它们都会立即运行,相隔几毫秒,并且从现在开始在内部定时器的给定时间内解析!

如果你想运行一个接一个的承诺,他们必须以某种方式被包裹,使他们不跑,现在,但每当他们被称为,例如像

var tasks = [
    _ => new Promise(resolve => {
            order.push(1);
            setTimeout(() => {
                order.push(2)
                resolve();
            }, 100);
    }),
    _ => new Promise(resolve => {
            order.push(3);
            setTimeout(() => {
                order.push(4)
                resolve();
            }, 100);
    }),
    _ => new Promise(resolve => {
            order.push(5);
            resolve();
    }),
];
Run Code Online (Sandbox Code Playgroud)

(下划线是有效的ES2015匿名箭头功能简写)

其中每个数组值都是可以调用的匿名函数,并且在调用时,promise构造函数会运行并返回promise.

要以串行方式递归调用函数,递归函数调用是最简单的,当电流完成时调用下一个函数.

(function iterate(i) {
    tasks[i]().then(() => {          // when done
        if (tasks[++i]) iterate(i);  // call the next one
    });
})(0);
Run Code Online (Sandbox Code Playgroud)

小提琴


编辑:

Array.reduce既然您拥有返回承诺的函数,那么您也可以按照自己的方式进行操作

tasks.reduce((cur, next) => cur.then(next), Promise.resolve()).then(() => {
    // all done, chain is complete !
});
Run Code Online (Sandbox Code Playgroud)