一个 async function 数组, 怎样一个一个顺序执行?

2021-10-23 16:14:56 +08:00
 selfcreditgiving

想做到的是,每过一秒,分别打印:
this is 0
this is 1
this is 2
~
this is 8

下面的代码结果是过一秒后全部执行。

是不是哪里写的不对呢,多谢指教

var jobs = [];

for(let i = 0; i < 8; i++) {
    jobs.push(async function(){
        setTimeout(function(){
            console.log("this is " + i)
        },1000)
    });
}

(async function () {
    for (const job of jobs) {
        await job()
    }
        
})();
3063 次点击
所在节点    JavaScript
20 条回复
ruxuan1306
2021-10-23 16:18:39 +08:00
```
const job = new Promise((resolve, reject) => {
setTimeout(() => resolve, 3000)
})

console.log('start')
await job()
console.log('done')
```
ruxuan1306
2021-10-23 16:20:08 +08:00
async 只是 promise 的语法糖,await 本质上必须等待一个 promise ,如果 await 一个立即数,则会立即 resolve 。
setTimeout 返回的是 timer 的 id ,是一个立即数,所以会立即 resolve ,你必须返回一个 promise 。
codehz
2021-10-23 16:21:03 +08:00
var jobs = [];

for(let i = 0; i < 8; i++) {
jobs.push(() => new Promise(resolve => setTimeout(() => {
console.log("this is " + i);
resolve();
},1000)));
}

(async function () {
for (const job of jobs) {
await job()
}
})();
MonkeyD1
2021-10-23 16:21:17 +08:00
var jobs = [];

for (let i = 0; i < 8; i++) {
jobs.push(async function () {
return new Promise(function (resolve, reject) {
setTimeout(function () {
resolve(console.log("this is " + i));
}, 1000);
});
});
}

(async function () {
for (const job of jobs) {
await job();
}
})();
MonkeyD1
2021-10-23 16:22:33 +08:00
return promise
Curtion
2021-10-23 16:23:06 +08:00
你得这样
```javascript
var jobs = [];

for(let i = 0; i < 8; i++) {
jobs.push(async function(){
return new Promise(resolve => {
setTimeout(function(){
console.log("this is " + i)
resolve()
},1000)
})
});
}

(async function () {
for (const job of jobs) {
await job()
}

})();
```
ruxuan1306
2021-10-23 16:23:48 +08:00
发现我代码里 resolve 漏了对括号,会导致无人调用 resolve 无限等待,我猜你应该明白该怎么改正。
selfcreditgiving
2021-10-23 16:29:52 +08:00
@ruxuan1306 @codehz @MonkeyD1 多谢多谢 一下就解决了,v 友圈厉害了
0Vincent0Zhang0
2021-10-23 16:37:35 +08:00
把 1000 改为 (i+1)*1000 [doge]
kaixuan1901
2021-10-23 17:12:14 +08:00
```javascript
function sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}

(async function() {
for (let i = 0; i < 8; i++) {
await sleep(1000);
console.log("This is " + i);
}
})();
```
wakaka
2021-10-23 22:47:31 +08:00
好好理解一下 promise
selfcreditgiving
2021-10-24 00:33:09 +08:00
@0Vincent0Zhang0 呵呵 这个头比较铁 :)
beyondstars
2021-10-24 14:37:21 +08:00
function makeAsyncFunc(outputNum) {
return async function () {
const now = new Date().valueOf();
console.log(`${now}: this is ${outputNum}`);
};
}

const funcs = [];
for (let i = 1; i <= 10; i++) {
funcs.push(makeAsyncFunc(i));
}

function execOneByOne(asyncFuncs) {
if (asyncFuncs.length === 0) {
return;
}

const currentFunc = asyncFuncs.shift();
currentFunc().then(() => {
setTimeout(() => execOneByOne(asyncFuncs), 1000);
});
};

execOneByOne(funcs);

思路是把任务调度和任务执行区分开。
xingguang
2021-10-25 10:07:36 +08:00
我看问题已经解决了,但是我稍微吐槽一下:var 和 let 混用让略微有点强迫症的我看着有点难受。
danhua
2021-10-25 15:24:19 +08:00
我的想法是可不可以用微任务和宏任务来解释这个。
wangtian2020
2021-10-25 17:29:16 +08:00
```
let i = 0
let prm = () => new Promise((resolve, reject) => {
setTimeout(() => {
console.log(i++);
resolve()
}, 1000)
}
)


; (async () => {
await prm()
await prm()
await prm()
await prm()
await prm()
await prm()
})()
```
注意,settimeout 1000 代表着一定会在 1000 毫秒之后返回,可能是 1001 毫秒,1010 毫秒,如果内部同步卡住 2000 毫秒都有可能。
photon006
2021-10-26 09:20:56 +08:00
把 setTimeout 封装成 delay 方法,放到 for 外边当成 utils 工具使用,for 改成 for await 串行执行,在 for await 内调用 delay()。
chenjiangui998
2021-10-26 14:58:06 +08:00
let jobs = []
for (let i = 0; i < 10; i++) {
let a = i
jobs.push(async () => {
console.log('this is', a)
})
}

let time = setInterval(() => {
if (jobs.length) {
jobs.shift()()
} else {
clearInterval(time)
}
}, 1000)

和异步不异步没有关系
2i2Re2PLMaDnghL
2021-10-27 00:40:34 +08:00
@danhua 无关,而是顺次执行 setTimeout ,根本没等回调返回就先去找下一个去了,是逻辑错误而不是机制问题。
async function 里面没有 await 会立刻变为 fulfilled ,await 可能不会发生调度?
cenbiq
2021-10-27 13:39:28 +08:00
@danhua 这恐怕只是没搞懂 js async/await 原理

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/810025

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX