我想澄清这一点,因为文件不是很清楚;

Q1: Promise.all(iterable)是按顺序还是并行处理所有的promise ?或者,更具体地说,它相当于运行链式承诺

p1.then(p2).then(p3).then(p4).then(p5)....

或者它是某种其他类型的算法,其中所有的p1, p2, p3, p4, p5等同时(并行)被调用,并且结果在所有解决(或一个拒绝)后立即返回?

问题2:如果承诺。所有的运行都是并行的,是否有一种方便的方法来运行一个可迭代对象?

注意:我不想使用Q或蓝鸟,而是所有本地ES6规格。


当前回答

Promise.all(iterable)执行所有承诺吗?

不,承诺不能“执行”。它们在创建时就开始执行任务——它们只表示结果——甚至在将它们传递给Promise.all之前,您就可以并行执行所有的任务。

的承诺。一切都只等着多次承诺。它不关心它们解析的顺序,也不关心计算是否在并行运行。

是否有一种方便的方法来连续运行一个可迭代对象?

如果你已经许下承诺,除了承诺,你别无他法。All ([p1, p2, p3,…])(没有序列概念)。但是如果你确实有一个异步函数的可迭代对象,你确实可以按顺序运行它们。基本上你需要从

[fn1, fn2, fn3, …]

to

fn1().then(fn2).then(fn3).then(…)

解决方案是使用Array::reduce:

iterable.reduce((p, fn) => p.then(fn), Promise.resolve())

其他回答

Bergi的回答让我使用Array.reduce走上了正确的轨道。

然而,为了让函数一个接一个地返回我的承诺,我必须添加更多的嵌套。

我真正的用例是一个文件数组,由于下游的限制,我需要按顺序一个接一个地传输…

这是我最后得出的结论:

getAllFiles().then( (files) => {
    return files.reduce((p, theFile) => {
        return p.then(() => {
            return transferFile(theFile); //function returns a promise
        });
    }, Promise.resolve()).then(()=>{
        console.log("All files transferred");
    });
}).catch((error)=>{
    console.log(error);
});

如前面的回答所示,使用:

getAllFiles().then( (files) => {
    return files.reduce((p, theFile) => {
        return p.then(transferFile(theFile));
    }, Promise.resolve()).then(()=>{
        console.log("All files transferred");
    });
}).catch((error)=>{
    console.log(error);
});

没有等到传输完成才开始另一个,而且“所有文件传输”的文本甚至在第一个文件传输开始之前就出现了。

不知道我做错了什么,但想分享对我有用的东西。

编辑:自从我写了这篇文章,我现在明白为什么第一个版本不起作用了。Then()期望函数返回一个promise。因此,您应该传入不带括号的函数名!现在,我的函数需要一个参数,所以我需要封装在一个匿名函数中,不带参数!

也可以使用递归函数用异步函数顺序处理可迭代对象。例如,给定一个数组a,使用异步函数someAsyncFunction()处理:

var a = [1, 2, 3, 4, 5, 6] function someAsyncFunction(n) { return new Promise((resolve, reject) => { setTimeout(() => { console.log("someAsyncFunction: ", n) resolve(n) }, Math.random() * 1500) }) } //You can run each array sequentially with: function sequential(arr, index = 0) { if (index >= arr.length) return Promise.resolve() return someAsyncFunction(arr[index]) .then(r => { console.log("got value: ", r) return sequential(arr, index + 1) }) } sequential(a).then(() => console.log("done"))

只是详细阐述一下@Bergi的回答(非常简洁,但很难理解;)

这段代码将运行数组中的每一项,并将下一个'then chain'添加到末尾:

function eachorder(prev,order) {
        return prev.then(function() {
          return get_order(order)
            .then(check_order)
            .then(update_order);
        });
    }
orderArray.reduce(eachorder,Promise.resolve());

我一直在用for来求解连续的承诺。我不确定这是否有帮助,但这就是我一直在做的。

async function run() {
    for (let val of arr) {
        const res = await someQuery(val)
        console.log(val)
    }
}

run().then().catch()

你可以通过for循环来实现。

Async函数返回承诺:

async function createClient(client) {
    return await Client.create(client);
}

let clients = [client1, client2, client3];

如果你写下面的代码,那么客户端是并行创建的:

const createdClientsArray = yield Promise.all(clients.map((client) =>
    createClient(client);
));

但是如果你想按顺序创建客户端,那么你应该使用for循环:

const createdClientsArray = [];
for(let i = 0; i < clients.length; i++) {
    const createdClient = yield createClient(clients[i]);
    createdClientsArray.push(createdClient);
}