【问题标题】:Node - Push functions into array for use with Promise.all [duplicate]节点 - 将函数推入数组以与 Promise.all 一起使用 [重复]
【发布时间】:2018-07-25 07:09:58
【问题描述】:

我正在试验 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 才会运行。

我想我要问的是是否有一种方法可以“查询”这些函数,以便在我运行 Promise.all() 之前它们不会立即运行?

编辑 2:

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

如果不可能,请告诉我。

【问题讨论】:

  • 你期待什么输出?你期待[10, 20, 30] 在承诺中吗?
  • 现在,您已经完全改变了您的问题。您是否因为我回答您最初的问题而对我的回答投了反对票?
  • 我没有投反对票。
  • “在你调用 [promise.all] 之后才会运行承诺的印象”是可疑的。 a) Promise 不会运行,它们是接口对象。 b) 提供给 Promise 构造函数的 executor 函数被同步调用,并在构造函数返回创建的新 Promise 对象之前返回。记录的输出完全符合预期,因为您已将结果记录在计时器回调中,这些回调的执行顺序与放置在计时器队列中的顺序相同。在进行承诺组合之前指定任务要求可能会有所帮助。

标签: javascript node.js promise


【解决方案1】:

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

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

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

// 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.all”,您只需将 promises 数组传递给您所评论的 Promise.allPromise.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]
});

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

var params = [10, 20, 30];

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

把这些放在一起,你会像这样使用 Promise:

// 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]

在您的控制台中。

【讨论】:

  • OP 改变了他们的问题。它显然不再是关于Promise.all()
猜你喜欢
  • 2020-04-21
  • 2016-04-20
  • 1970-01-01
  • 2011-12-01
  • 2013-10-02
  • 2013-11-29
  • 2019-05-27
  • 2017-11-25
  • 2018-09-18
相关资源
最近更新 更多