采取以下循环:
for(var i=0; i<100; ++i){
let result = await some_slow_async_function();
do_something_with_result();
}
await
阻止循环吗?或者i
时await
继续递增?
关于do_something_with_result()
,i
的顺序是否有序保证?或者它取决于每个await
的{{1}} ed函数的速度有多快?
答案 0 :(得分:39)
- 时
await
阻止循环吗?或者在i
ing?await
是否会继续增加? 醇>
“阻止”不是正确的词,但是, i 在等待时不会继续增加。相反,执行会跳回到调用async
函数的位置,提供一个promise作为返回值,继续执行函数调用之后的其余代码,直到代码堆栈被清空为止。然后当等待结束时,恢复功能的状态,并在该功能内继续执行。只要该函数返回(完成),就会解决之前返回的相应承诺。
- 醇>
do_something_with_result()
的顺序是i
保证顺序吗?或者它取决于每个await
的{{1}} ed函数的速度有多快?
订单有保证。 i
之后的代码也保证仅在调用堆栈清空后才执行,即至少在下一个微任务执行时或之后执行。
查看此代码段中的输出结果。请特别注意“调用测试后”的位置:
await
答案 1 :(得分:9)
正如@realbart所说,它会阻止循环,然后循环调用。
如果您想要触发大量等待操作然后再一起处理它们,您可以执行以下操作:
document.onDomReady = function(){
adShow = 0;
document.onmousemove = function(){
if (adShow == 0) {
var leaderboard = CODE_FOR_AD;
var adLeaderboard = document.querySelector('.adspace-leaderboard#adspace');
adLeaderboard.innerHTML = leaderboard;
adShow = 1;
}
}
}
答案 2 :(得分:6)
您可以在“FOR LOOP”中测试async / await,如下所示:
(async () => {
for (let i = 0; i < 100; i++) {
await delay();
console.log(i);
}
})();
function delay() {
return new Promise((resolve, reject) => {
setTimeout(resolve, 100);
});
}
答案 3 :(得分:0)
没有阻止任何事件循环,请参见下面的示例
array (
'input' => '312',
'solutions' =>
array (
0 =>
array (
'sequence' => '222',
'steps' => 2,
),
),
)
array (
'input' => '334',
'solutions' =>
array (
0 =>
array (
'sequence' => '333',
'steps' => 1,
),
),
)
array (
'input' => '39',
'solutions' =>
array (
0 =>
array (
'sequence' => '33',
'steps' => 6,
),
1 =>
array (
'sequence' => '99',
'steps' => 6,
),
),
)
答案 4 :(得分:0)
async
函数返回一个Promise,该对象最终将“解析”为一个值,或因错误而“拒绝”。 await
关键字表示要等到该值(或错误)完成后才能使用。
因此,从运行功能的角度来看,它阻止等待慢速异步功能的结果。另一方面,javascript引擎会发现此功能已被阻止等待结果,因此它将检查事件循环(例如,单击新鼠标或连接请求等),以查看是否还有其他情况它可以继续使用直到返回结果。
但是请注意,如果慢速异步功能很慢,因为它正在您的javascript代码中计算很多东西,则javascript引擎将没有很多资源来做其他事情(而做其他事情很可能会使慢速异步功能,甚至更慢)。异步功能真正发挥作用的地方在于进行I / O密集型操作,例如查询数据库或传输大文件,而javascript引擎运行良好,并真正在等待其他内容(例如数据库,文件系统等)。
以下两个代码在功能上是等效的:
let result = await some_slow_async_function();
和
let promise = some_slow_async_function(); // start the slow async function
// you could do other stuff here while the slow async function is running
let result = await promise; // wait for the final value from the slow async function
在上面的第二个示例中,慢速异步函数在没有await
关键字的情况下被调用,因此它将开始执行该函数并返回一个Promise。然后,您可以做其他事情(如果有其他事情要做)。然后使用await
关键字进行阻止,直到承诺实际上“解决”为止。因此,从for
循环的角度来看,它将同步运行。
所以:
是的,await
关键字具有阻止正在运行的功能的作用,直到异步功能“解析”一个值或“拒绝”一个错误,但是它不会阻止javascript引擎,如果它在等待时还有其他事情要做,它仍然可以做其他事情
是的,循环的执行将是连续的
http://javascript.info/async上有一个很棒的教程。
答案 5 :(得分:0)
ad 1.是。否
ad 2.是。不。
证明:
async function start()
{
console.log('Start');
for (var i = 0; i < 10; ++i) {
let result = await some_slow_async_function(i);
do_something_with_result(i);
}
console.log('Finish');
}
function some_slow_async_function(n) {
return new Promise(res => setTimeout(()=>{
console.log(`Job done: ${(2000/(1+n))|0} ms`);
res(true);
},2000/(1+n)));
}
function do_something_with_result(n) {
console.log(`Something ${n}`);
}
start();
答案 6 :(得分:0)
这是我针对这个有趣问题的测试解决方案:
import crypto from "crypto";
function diyCrypto() {
return new Promise((resolve, reject) => {
crypto.pbkdf2('secret', 'salt', 2000000, 64, 'sha512', (err, res) => {
if (err) {
reject(err)
return
}
resolve(res.toString("base64"))
})
})
}
setTimeout(async () => {
console.log("before await...")
const a = await diyCrypto();
console.log("after await...", a)
}, 0);
setInterval(() => {
console.log("test....")
}, 200);
在setTimeout的回调中,await
阻止了执行。但是setInterval
一直在运行,因此事件循环像往常一样运行。
答案 7 :(得分:-2)
等待阻塞循环吗?还是
i
在等待期间继续增加?
否,await不会阻止循环。是的,i
在循环时继续增加。
关于
i
的do_something_with_result()的顺序是否保证是连续的?还是取决于每个i
的等待功能有多快?
依次保证do_something_with_result()
的顺序,但不能保证i
的顺序。这取决于等待的功能运行的速度。
所有对some_slow_async_function()
的调用都被分批处理,即,如果do_something_with_result()
是console
,那么我们将看到它显示了循环运行的次数。然后依次执行,之后将执行所有的等待调用。
为更好地了解,您可以在以下代码段中运行:
async function someFunction(){
for (let i=0;i<5;i++){
await callAPI();
console.log('After', i, 'th API call');
}
console.log("All API got executed");
}
function callAPI(){
setTimeout(()=>{
console.log("I was called at: "+new Date().getTime())}, 1000);
}
someFunction();
一个人可以清楚地看到在整个for循环中如何首先打印行console.log('After', i, 'th API call');
,然后在执行完所有代码后从callAPI()
获取结果。
因此,如果等待后的行取决于从等待调用获得的结果,则它们将无法按预期工作。
最后,await
中的for-loop
不能确保成功完成从 等待调用 获得的结果的操作,这可能需要一些时间才能完成。
在节点中,如果将neo-async
库与waterfall
一起使用,则可以实现这一目标。