gpt4 book ai didi

javascript - 当await表达式是concat()的参数时,为什么async/await有不同的输出?

转载 作者:行者123 更新时间:2023-12-04 12:31:10 25 4
gpt4 key购买 nike

我对下面的例子感到困惑。

我明白为什么output2[1000,2000,3000]因为闭包,这就是 map() 中所有异步函数的原因更新相同的数组output2 。 (如果我的概念有误,请纠正。)

但是,我不明白为什么output1[3000] .

请问为什么run1行为不像 run2 ?你能告诉我其中的区别吗?

"use strict";

function sleep(ms) {
return new Promise(resolve =>
setTimeout(() => {
resolve(ms);
}, ms)
);
}

const seconds = [1000, 3000, 2000];

let output1 = [];
let output2 = [];

(async function run1() {
await Promise.all(
seconds.map(async sec => {
output1 = output1.concat([await sleep(sec)]);
})
);
console.log({ output1 });
})();

(async function run2() {
await Promise.all(
seconds.map(async sec => {
const res = await sleep(sec);
output2 = output2.concat([res]);
})
);
console.log({ output2 });
})();

最佳答案

查看声明

 output1 = output1.concat([await sleep(sec)]);

左侧output1是一个变量标识符,用于提供存储右侧计算结果的位置。变量的绑定(bind)不会改变,并且始终提供变量值的位置。

右侧output1是一个值 - 从变量名称提供的位置检索的值。

现在,如果 JavaScript 引擎在继续计算之前检索 output1 的值,则所有三个映射函数调用

  • 检索对存储在输出中的空数组的引用,
  • 等待计时器 promise 并将output1设置为新值,即从concat方法返回的数组。

因此,每个映射操作都会将一个包含计时器值的数组连接到一个空数组,并将结果存储在 output1覆盖之前等待的操作的结果

这解释了为什么当 Promise.all 确定时,您只能看到存储在 output1 中的最后一个数组。我还将收回上面“如果 JavaScript 引擎...”的措辞。 JavaScript 引擎确实在 await 之前获取了 output1 的值:

function sleep(ms) {
return new Promise(resolve =>
setTimeout(() => {
console.log( output1.length);
resolve(ms);
}, ms)
);
}

const seconds = [1000, 3000, 2000];

let output1 = [];
let output2 = [];

(async function run1() {
await Promise.all(
seconds.map(async sec => {
output1 = output1.concat([await sleep(sec)]);
//output1.push(await sleep(sec));
console.log(output1[0]);
})
);
console.log({ output1 });
})();

let count = 6;
let timer = setInterval( ()=> {
console.log(output1[0])
if(--count <=0 ) {
clearInterval( timer);
}
}, 500);


要弄清楚为什么第二种方法(run2)有效(与闭包的存在无关):

.map 方法同步调用映射函数,并且调用同步返回一个 promise ,而无需等待计时器 promise 履行。

在第二个版本中,

seconds.map(async sec => {
const res = await sleep(sec);
output2 = output2.concat([res]);
}

const res = wait sleep(sec) 行保存执行上下文并等待 sleep promise 履行。当 promise 完成时,await 恢复保存的上下文并将 promise 值存储在 res 中。下一行

  ouput2 = output2.concat([res]);

在计时器到期后执行,并且在执行该行时,右侧将加载当前output2的值,如上一个计时器到期时更新的值(如果有)发生了。

将此与 run1 进行对比,其中 JavaScript 引擎在开始计算赋值运算符右侧的表达式并使用所有迭代的空数组值相同,如代码片段中所示。

*accepted answer重复项表示在 await 返回右侧操作数之前从存储中检索加法运算的左侧操作数。在 run1 的情况下,我们看到将调用方法的对象(output1 的值)在该值之前检索用于调用该方法的参数已确定。正如链接答案的评论中所述,这是一个相当“隐藏的陷阱”。

关于javascript - 当await表达式是concat()的参数时,为什么async/await有不同的输出?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/69009288/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com