Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/node.js/33.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 等待与承诺_Javascript_Node.js_Promise_Async Await_For Await - Fatal编程技术网

Javascript 等待与承诺

Javascript 等待与承诺,javascript,node.js,promise,async-await,for-await,Javascript,Node.js,Promise,Async Await,For Await,这两者之间有什么区别吗: const promises=wait Promise.all(items.map(e=>somethingAsync(e)); 用于(承诺的常数){ //做一些计算 } 这个呢 wait的(items.map的常数(e=>somethingAsync(e))){ //做一些计算 } 我知道在第一个片段中,所有的承诺都是同时发出的,但我不确定第二个。for循环是否等待第一次迭代完成以调用下一个promise?或者所有的承诺都是同时发出的,而循环的内部就像是对它们的回

这两者之间有什么区别吗:

const promises=wait Promise.all(items.map(e=>somethingAsync(e));
用于(承诺的常数){
//做一些计算
}
这个呢

wait的
(items.map的常数(e=>somethingAsync(e))){
//做一些计算
}

我知道在第一个片段中,所有的承诺都是同时发出的,但我不确定第二个。for循环是否等待第一次迭代完成以调用下一个promise?或者所有的承诺都是同时发出的,而循环的内部就像是对它们的回调?

正如你所说的
承诺。所有的
都会一次性发送所有请求,然后当所有请求都完成时,你会得到响应

在第二个场景中,您将一次性发送请求,但会逐个收到响应

请参见此小示例以供参考

let i = 1;
function somethingAsync(time) {
  console.log("fired");
  return delay(time).then(() => Promise.resolve(i++));
}
const items = [1000, 2000, 3000, 4000];

function delay(time) {
  return new Promise((resolve) => { 
      setTimeout(resolve, time)
  });
}

(async() => {
  console.time("first way");
  const promises = await Promise.all(items.map(e => somethingAsync(e)));
  for (const res of promises) {
    console.log(res);
  }
  console.timeEnd("first way");

  i=1; //reset counter
  console.time("second way");
  for await (const res of items.map(e => somethingAsync(e))) {
    // do some calculations
    console.log(res);
  }
  console.timeEnd("second way");
})();

你也可以在这里试试-


希望这会有所帮助。

实际上,使用
for await
语法确实会立即触发承诺

这段代码证明了这一点:

const sleep=s=>{
返回新承诺(解决=>{
设置超时(解析,s*1000);
});
}
const somethingAsync=async t=>{
等待睡眠(t);
返回t;
}
(异步()=>{
常量项=[1,2,3,4];
const now=Date.now();
对于wait(items.map的常数(e=>somethingAsync(e))){
控制台日志(res);
}
log(“时间:,(Date.now()-now)/1000);
})();
标准:
时间:4.001

但是循环的内部并不起“回调”的作用。如果我反转数组,所有日志将立即显示。我假设承诺立即被触发,运行时只等待第一个承诺被解析,然后进入下一个迭代


编辑:事实上,当我们将
用于wait
而不是异步迭代器时,使用
是不好的做法,最好是使用
Promise。根据@Bergi在其回答中的说法,所有的

是的,它们完全不同<代码>for await
应该与异步迭代器一起使用,而不是与预先存在的承诺数组一起使用

只是想说明一下

for await (const res of items.map(e => somethingAsync(e))) …
工作原理与

const promises = items.map(e => somethingAsync(e));
for await (const res of promises) …

somethingsync
调用在等待任何东西之前立即发生。然后,他们一个接一个地等待,如果其中任何一个被拒绝,这肯定是一个问题:这将导致未处理的承诺拒绝错误使用
承诺。all
是处理承诺数组的唯一可行选择

for (const res of await Promise.all(promises)) …

有关详细信息,请参见和。

在异步迭代器上,当前迭代的计算取决于以前的一些迭代时,需要使用等待…
。如果没有依赖关系,
承诺。一切由您选择。wait的
构造被设计为与异步迭代器一起工作,尽管-在您的示例中,您可以将它与一系列承诺一起使用

有关使用异步迭代器的示例,请参见本书中的示例,该迭代器不能使用
Promise重写。所有

(异步()=>{
for wait(fetchCommits的const commit('javascript-tutorial/en.javascript.info')){
log(commit.author.login);
}
})();
这里,
fetchCommits
异步迭代器请求
fetch
GitHub repo的提交。
fetch
以30次提交的JSON响应,并在
link
标题中提供指向下一页的链接因此,下一次迭代只能在上一次迭代具有下一个请求的链接后开始

异步函数*fetchCommits(repo){
让url=`https://api.github.com/repos/${repo}/commits`;
while(url){
const response=wait fetch(url,{
标题:{'User-Agent':'Our script'},
});
const body=await response.json();/(提交数组)
//下一页的URL位于标题中,请使用regexp将其解压缩
让nextPage=response.headers.get('Link').match(/;rel=“next”/);
下一页=下一页?[1];
url=下一页;
for(let commit of body){//yield逐个提交,直到页面结束
屈服承诺;
}
}
}

事实上,你已经证明了我的第二点。使用
for wait
实际上同时触发了所有承诺,因此循环的执行时间为:4秒。如果它等待一个完成下一个,则总执行时间将为1+2+3+4=10秒。这是真的。添加了时间部分来证明这一点。IMO一系列承诺是assi类似于异步迭代器,因为它们将控件返回到事件循环,对吗?如果在我的
somethingsync
函数中,我正确捕获了所有内容呢?是的,数组提供了异步迭代器,这就是为什么循环不会抛出协议错误。但该迭代每次都在等待一个承诺,忽略错误当然,如果
somethingsync
从不出错,那么不会有什么不好的事情发生,但这很难保证。在承诺数组中使用
for await
仍然是一种不好的做法。好的,将使用
Promise.all
,感谢您的澄清非常清楚,谢谢。在您的代码示例中,
for await的行为类似于
yield*
不是吗?因为每次迭代都会产生多个项,所以没有生成器组合,每次提交只会产生一个
yield
。每30次迭代后,会加载一个新页面,接下来的30次提交都会被
yield
编辑。实际上,迭代之间的依赖性只会每30次发生一次。
for (const res of await Promise.all(promises)) …