Async/Await 未按预期使用 for 循环语句
Async/Await is not working as expected with for loop statement
我是 Javascript 和 nodejs 的新手。在尝试了解承诺和回调的工作原理时,我尝试在 'for' 循环中调用一个函数,如下所示。我试图实现的是使用承诺每 2 秒打印一次 'i' 值。但是,程序等待2秒,打印3次i值后退出。
for(let i = 0; i < 3 ; i++){
func(callback,i);
}
async function func(callback,i){
await callback(i);
}
function callback(i){
return new Promise((res,rej) =>{
setTimeout(()=>{
console.log('i = ',i)
res();
}, 2000);
})
}
谁能帮我理解为什么会这样?
这里有一些函数可以帮助您了解 promises 如何与数组一起工作,我们会在这些地方犯常见的错误。
function promiseFunction(v) {
return new Promise((resolve) => {
setTimeout(() => resolve(v), 1000);
});
}
function f1() {
[1, 2, 3, 4]. forEach(async(i) => {
const v = await promiseFunction(i);
console.log(`-f1 v- ${v}<br/>`);
});
console.log('all done<br/>');
}
async function f2() {
await Promise.all([1, 2, 3, 4].map(async(i) => {
const v = await promiseFunction(i);
console.log(`-f2 v- ${v}<br/>`);
}));
console.log('all done<br/>');
}
async function f3() {
await [1, 2, 3, 4].reduce((p, i) => {
return p.then(async () => {
const v = await promiseFunction(i);
console.log(`-f3 v- ${v}<br/>`);
});
}, Promise.resolve());
console.log('all done<br/>');
}
async function func() {
console.log('f1');
await f1();
console.log('f2');
await f2();
console.log('f3');
await f3();
}
func();
f1() 将首先打印 all done
,然后在一秒后立即打印 1,2,3,4。
f2() 将在一秒后立即打印 1,2,3,4 然后打印 all done
.
f3() 将每秒打印 1,2,3,4,然后打印 all done
.
你的异步函数 func 也是 returns 一个承诺,所以你需要在调用之前使用 await 关键字。
for(let i = 0; i < 3 ; i++){
await func(callback,i);
}
你可以用 async
立即执行的函数包装你的循环并在其中添加 await
(正如这里已经建议的那样):
(async () => {
for(let i = 0; i < 3 ; i++){
await callback(i);
}
})();
function callback(i){
return new Promise((res,rej) =>{
setTimeout(()=>{
console.log('i = ',i)
res();
}, 2000);
})
}
这是我在 Bergi 编辑之前的原始答案:
(async () => {
for(let i = 0; i < 3 ; i++){
await func(callback,i);
}
})()
async function func(callback,i){
await callback(i);
}
function callback(i){
return new Promise((res,rej) =>{
setTimeout(()=>{
console.log('i = ',i)
res();
}, 2000);
})
}
您需要等待异步函数完成
for(let i = 0; i < 3 ; i++){
await func(callback,i);
}
但是由于您不能在全局范围内使用 await
关键字,因此您需要将 for
循环包装在异步函数中,然后调用它
async function myTest(){
for(let i = 0; i < 3 ; i++){
await func(callback,i);
}
}
myTest()
你很接近。缺少的信息是 async
函数(你的 func()
)隐含地 returns 一个 AsyncFunction
对象,它隐含地 returns Promise 本身(doc)。
您使用 immediately invoked function expression 的代码将是
(async () => {
for(let i = 0; i < 3 ; i++){
await func(callback,i);
}
})()
async function func(callback,i){
await callback(i);
}
function callback(i){
return new Promise((res,rej) =>{
setTimeout(()=>{
console.log('i = ',i)
res();
}, 2000);
})
}
请注意,现在在大多数浏览器中原生可用的构造 for await..of
(doc)。你也可以试试这个。
我是 Javascript 和 nodejs 的新手。在尝试了解承诺和回调的工作原理时,我尝试在 'for' 循环中调用一个函数,如下所示。我试图实现的是使用承诺每 2 秒打印一次 'i' 值。但是,程序等待2秒,打印3次i值后退出。
for(let i = 0; i < 3 ; i++){
func(callback,i);
}
async function func(callback,i){
await callback(i);
}
function callback(i){
return new Promise((res,rej) =>{
setTimeout(()=>{
console.log('i = ',i)
res();
}, 2000);
})
}
谁能帮我理解为什么会这样?
这里有一些函数可以帮助您了解 promises 如何与数组一起工作,我们会在这些地方犯常见的错误。
function promiseFunction(v) {
return new Promise((resolve) => {
setTimeout(() => resolve(v), 1000);
});
}
function f1() {
[1, 2, 3, 4]. forEach(async(i) => {
const v = await promiseFunction(i);
console.log(`-f1 v- ${v}<br/>`);
});
console.log('all done<br/>');
}
async function f2() {
await Promise.all([1, 2, 3, 4].map(async(i) => {
const v = await promiseFunction(i);
console.log(`-f2 v- ${v}<br/>`);
}));
console.log('all done<br/>');
}
async function f3() {
await [1, 2, 3, 4].reduce((p, i) => {
return p.then(async () => {
const v = await promiseFunction(i);
console.log(`-f3 v- ${v}<br/>`);
});
}, Promise.resolve());
console.log('all done<br/>');
}
async function func() {
console.log('f1');
await f1();
console.log('f2');
await f2();
console.log('f3');
await f3();
}
func();
f1() 将首先打印 all done
,然后在一秒后立即打印 1,2,3,4。
f2() 将在一秒后立即打印 1,2,3,4 然后打印 all done
.
f3() 将每秒打印 1,2,3,4,然后打印 all done
.
你的异步函数 func 也是 returns 一个承诺,所以你需要在调用之前使用 await 关键字。
for(let i = 0; i < 3 ; i++){
await func(callback,i);
}
你可以用 async
立即执行的函数包装你的循环并在其中添加 await
(正如这里已经建议的那样):
(async () => {
for(let i = 0; i < 3 ; i++){
await callback(i);
}
})();
function callback(i){
return new Promise((res,rej) =>{
setTimeout(()=>{
console.log('i = ',i)
res();
}, 2000);
})
}
这是我在 Bergi 编辑之前的原始答案:
(async () => {
for(let i = 0; i < 3 ; i++){
await func(callback,i);
}
})()
async function func(callback,i){
await callback(i);
}
function callback(i){
return new Promise((res,rej) =>{
setTimeout(()=>{
console.log('i = ',i)
res();
}, 2000);
})
}
您需要等待异步函数完成
for(let i = 0; i < 3 ; i++){
await func(callback,i);
}
但是由于您不能在全局范围内使用 await
关键字,因此您需要将 for
循环包装在异步函数中,然后调用它
async function myTest(){
for(let i = 0; i < 3 ; i++){
await func(callback,i);
}
}
myTest()
你很接近。缺少的信息是 async
函数(你的 func()
)隐含地 returns 一个 AsyncFunction
对象,它隐含地 returns Promise 本身(doc)。
您使用 immediately invoked function expression 的代码将是
(async () => {
for(let i = 0; i < 3 ; i++){
await func(callback,i);
}
})()
async function func(callback,i){
await callback(i);
}
function callback(i){
return new Promise((res,rej) =>{
setTimeout(()=>{
console.log('i = ',i)
res();
}, 2000);
})
}
请注意,现在在大多数浏览器中原生可用的构造 for await..of
(doc)。你也可以试试这个。