【问题标题】:JS: what's the different in Promise.allJS:Promise.all 有什么不同
【发布时间】:2022-01-06 02:51:13
【问题描述】:

我只是想知道await Promise.all([/* ... /*]) 的这两个电话之间是否有不同 在我的性能测试中,用了同样的时间。

这是我要被 Promise.all 调用的方法:

const makeFetch1 = async () => {
  axios.get("https://jsonplaceholder.typicode.com/todos/1");
};

const makeFetch2 = async () => {
  return axios.get("https://jsonplaceholder.typicode.com/todos/1");
};

1) await Promise.all([makeFetch1(), makeFetch1(), ...])
2) await Promise.all([makeFetch2(), makeFetch2(), ...])

两者的执行时间结果相同,我应该选择什么?

【问题讨论】:

  • 请注意,第一个箭头函数不会返回任何超出异步包装承诺的内容。只有单语句箭头函数返回数据,当你在大括号内有一个函数体时,你需要一个 return 关键字。
  • 如果你在异步函数中没有 return 任何东西,它会返回一个带有 undefined 值的承诺。
  • 第一个使用Promise.all() 是没有意义的,因为它根本没有监控任何承诺。当fetch() 操作继续运行并最终完成时,它将立即解决。第二个跟踪 Promise 和 resolve,当它们同时解析并使用它们的值解析时。
  • 我要补充一点,[makeFetch1, ...][makeFetch2, ...] 不会调用 makeFetch* 函数。你需要写Promise.all([makeFetch2(), ...])
  • 如果您问(...) => { ... }(...) => ... 之间的性能差异是什么,请测量一下。 stackoverflow 不适合这类问题。

标签: javascript promise nodes


【解决方案1】:

第一个将触发请求而不返回它。所以makeFetch1() 将产生一个立即解决的承诺。这几乎肯定不是你想要的。异步函数应该在某个地方 awaitreturn ,否则它也可能是一个标准函数(不返回任何内容)。

即使您不关心请求解析为什么,您仍然应该使用请求的结果(通过返回或awaiting,这样您就可以查看请求是否成功 - 并与用户如果失败则有问题)

第二个将触发请求并返回它。所以makeFetch1() 将产生一个 Promise,一旦请求解决 - 这可能需要几毫秒。

【讨论】:

  • 它们的性能相同,是吗? :)
  • @BallonUra 他们做的事情不同,所以比较性能没有意义。
【解决方案2】:

有几个主要区别和多个编码错误。

首先关闭此代码:

const makeFetch1 = async () => {
  axios.get("https://jsonplaceholder.typicode.com/todos/1");
};

是一个async 函数,它调用axios.get(),然后立即返回一个已经解析并具有undefined 解析值的promise。这里没有任何东西等待axios.get() 调用完成。

你的第二个代码块:

const makeFetch2 = async () => {
  return axios.get("https://jsonplaceholder.typicode.com/todos/1");
};

调用axios.get() 并返回它创建的承诺。因此,此函数返回的承诺将与 axios.get() 调用完成时绑定,并且解析的值将是 axios 调用的解析值。

区别:

  1. 您可以使用makeFetch2() 函数来获取axios.get() 调用的结果(解析值或拒绝错误)。您不能使用makeFetch1() 来获取axios.get() 调用的结果,因为该结果不会以任何方式传回给调用者。

  2. 同样,makeFetch2() 将允许调用者知道 axios 操作何时完成。 makeFetch1() 不会。

  3. 如果axios.get() 操作被拒绝,那么makeFetch1() 将导致未处理的拒绝错误,因为没有任何东西在监听拒绝。

那么,这两个:

await Promise.all([makeFetch1, makeFetch1, ...])
await Promise.all([makeFetch2, makeFetch2, ...])

两者都非常无用,因为您没有调用任何函数,因此没有执行任何操作。这些都将立即使用函数引用数组的解析值解析。没有执行任何 axios 调用,因为实际上没有调用 makeFetch1()makeFetch2()


如果你打算用这两个来实际执行函数:

await Promise.all([makeFetch1(), makeFetch1(), ...])
await Promise.all([makeFetch2(), makeFetch2(), ...])

然后,第一个将立即使用 undefined 值数组作为已解析值解析,因为请记住 makeFetch1() 返回值与 axios.get() 调用没有任何关联。

第二个将正确等待makeFetch2() 中的所有axios.get() 调用完成,并将使用来自axios.get() 调用的一组值进行解析。


两者的执行时间结果相同,我应该选择什么?

这是因为当您实现它们时,在任何一种情况下都不会调用 makeFetchN() 函数。因此,它们什么都不做,因此具有相同的执行时间。

如果您将实现更改为实际调用函数,如下所示:

await Promise.all([makeFetch1(), makeFetch1(), ...])
await Promise.all([makeFetch2(), makeFetch2(), ...])

将存在显着的时间差异,因为基于 makeFetch1() 的调用不会等待任何 axios.get() 调用完成,也不会返回结果或完成,并且会遭到未捕获的拒绝。

基于makeFetch1() 的那个没有实际用途,你可以这样做:

makeFetch1();
makeFetch1();
...

结果完全相同,因为 makeFetch1() 只是返回一个立即解决的承诺,因此将它们全部传递给 Promise.all() 并没有做任何有用的事情。

makeFetch1() 可能只是没有用,因为它不会通知调用者完成、错误或已解决的值。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-01-24
    • 1970-01-01
    • 2020-01-24
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多