节点 - 将函数推送到数组以与Promise.all

时间:2018-02-14 16:23:24

标签: javascript node.js promise

我正在尝试使用Promise.all,但是当我将它们推入数组时,函数会运行,那么promise.all的重点是什么?这是一个例子:

async function foo(args) {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            console.log(args)
            resolve(args)
        }, 500)
    });
}

function init() {
    var params = [10, 20, 30];
    var promises = [];

    for (let x of params) {
        promises.push(foo(x));
    }

    //do something with Promise.all(promises) here

    return;
}


init();

输出:

10
20
30

我做错了什么?我确定这是愚蠢的,我可能会失明。

修改 对不起,我应该澄清,我知道如何实际调用Promise.all,但我的印象是承诺在你打电话之后才会运行。

我想我要问的是,是否有办法对这些函数进行“排队”,以便在运行Promise.all()之前它们不会立即运行?

编辑2:

我看到这被标记为复制/人们说它不是关于promise.all,我希望尽可能将函数排在最后与promise.all一起使用,而不是按照建议手动执行操作链接的帖子。

如果不可能,请告诉我。

1 个答案:

答案 0 :(得分:3)

好的,首先让我们看一下你的foo函数。

这里有一个已经解决为Promise的Promise。 async function声明的作用是有效地使函数返回一个承诺。

这意味着您可以在await函数中使用async,而无需担心函数解析。例如:

// Lets say you have a 'long running' function that returns a promise.
const timeout = ms =>  new Promise(
    resolve => setTimeout(resolve, ms)
);

// What you can do is something like so:
async function foo(args) {
    await timeout(500);

    console.log(args);
    return args;
}

'timeout' function来自@Bergi。 这与您的第一个foo函数几乎完全相同。

// Lets say you 'foo' here.
const fooPromise = foo('Your args');

// The output here would be a pending Promise
// in chrome console: Promise {<pending>}

您的foo代码的作用实际上是相同的,除非它在实践中做了类似的事情:

function foo(args) {
    return new Promise(resolve1 => {
        return new Promise((resolve, reject) => {
            setTimeout(() => {
                console.log(args)
                resolve(args)
            }, 500)
        });
    });
}

这是多余的,但不会对程序的运行方式产生负面影响。

其次,让我们看一下init函数。

在JavaScript中,您不需要使用'Init','Main'或任何等效项。 您可以开始运行代码,这样您的init代码就可以从函数中删除并执行,如下所示:

var params = [10, 20, 30];
var promises = [];

for (let x of params) {
    promises.push(foo(x));
}

//do something with Promise.all(promises) here

现在再次制作Promise,你的代码没有什么“错误”。 要在此处使用“Promise.all”,您只需将promises数组传递给Promise.all,就像您评论的那样。 Promise.all会返回Promise,其中包含您生成的promises数组。然后,您可以像访问任何其他Promise一样访问它。

// Use your promises
Promise.all(promises)

// Do what you need to do with the Promises
.then(output => {
    // Output = [10, 20, 30]
});

可以使用Array.prototype.map替换使用'for循环'的代码,以快速生成一系列承诺,如下所示:

var params = [10, 20, 30];

Promise.all(params.map(foo))
.then(output => {
    // Output = [10, 20, 30]
});

将这些放在一起你会使用这样的承诺:

// A 'long running' function that returns a promise.
const timeout = ms =>  new Promise(
    resolve => setTimeout(resolve, ms)
);

// What you can do is something like so:
async function foo(args) {
    // A 'long running' function that returns a promise.
    await timeout(500);

    // Here you can manipulate the args like normal
    // e.g.:
    args = args ** 2;

    console.log(args);
    return args;
}

var params = [10, 20, 30];

Promise.all(params.map(foo))
.then(output => {
    // output = [100, 400, 900]
    console.log(output);
});

这个的输出是:

100
400
900
[100, 400, 900]

在你的控制台中。