一道面试题引发的思考6

一个前端交流群的一道面试题

只修改start方法,实现id 从0到4 依次输出

1
2
3
4
5
6
7
/*
id:0
id:1
id:2
id:3
id:4
*/
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
function start(id) {   // 只修改start方法,实现id ** 从0到4 ** 依次输出
execute(id).catch(console.log);
}

for(let i = 0; i < 5; i++) {
start(i);
}

function sleep() {
const dur = Math.floor(Math.random() * 500);
return new Promise((res, rej) => {
setTimeout(() => {
res();
}, dur)
})
}

function execute(id) {
return sleep().then(() => {
console.log('id:' + id);
});
}

因为for循环会立即触发,所以只修改start方法有些难度!!!

如果不考虑代码修改范围,可以实现for of等方法。可参考async 并发执行和继发执行

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
(async ()=> {
for(let i = 0; i < 5; i++) {
await execute(i).catch(console.log)
}
})()

function sleep() {
const dur = Math.floor(Math.random() * 500);
return new Promise((res, rej) => {
setTimeout(() => {
res();
}, dur)
})
}

function execute(id) {
return sleep().then(() => {
console.log('id:' + id);
});
}

投机取巧1

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
function start(id) {
setTimeout(() => {
execute(id).catch(console.log);
}, id*500); // 可能会和sleep()的setTimeout冲突,js单线程的坑
}

for(let i = 0; i < 5; i++) {
start(i);
}

function sleep() {
const dur = Math.floor(Math.random() * 500);
return new Promise((res, rej) => {
setTimeout(() => {
res();
}, dur)
})
}

function execute(id) {
return sleep().then(() => {
console.log('id:' + id);
});
}

投机取巧2

1
2
3
function start(id) {
console.log('id:' + id);
}

我的答案1

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
async function start(i, isDg) {
if(isDg) {
if(start.arr.length) {
await execute(start.arr.shift()).then(() => {
start('', true);
});
}
} else {
if(start.arr) {
start.arr.push(i)
} else {
start.arr = [];
start.arr.push(i);
start('', true);
}
}
}

for(let i = 0; i < 5; i++) {
start(i);
}

function sleep() {
const dur = Math.floor(Math.random() * 500);
return new Promise((res, rej) => {
setTimeout(() => {
res();
}, dur)
})
}

function execute(id) {
return sleep().then(() => {
console.log('id:' + id);
});
}
以下方法都会污染this

我的答案2

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
function start(id) {
if(!this.processList) this.processList = [];
this.processList.push({
id
});
clearTimeout(this.t);
this.t = setTimeout(() => {
(async() => {
let target = this.processList.shift();
while(target) {
await execute(target.id);
target = this.processList.shift();
}
})();
}, 0);
}

for(let i = 0; i < 5; i++) {
start(i);
}

function sleep() {
const dur = Math.floor(Math.random() * 500);
return new Promise((res, rej) => {
setTimeout(() => {
res();
}, dur)
})
}

function execute(id) {
return sleep().then(() => {
console.log('id:' + id);
});
}

我的答案3

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
function start(id) {
this.promises = !this.promises ?
execute(id) :
this.promises.then(() => execute(id));
}

for(var i = 0; i < 5; i++) {
start(i);
}

function sleep() {
const dur = Math.floor(Math.random() * 500);
return new Promise((res, rej) => {
setTimeout(() => {
res();
}, dur)
})
}

function execute(id) {
return sleep().then(() => {
console.log('id:' + id);
});
}

我的答案4

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
async function start(id) {
if(!this.task) {
this.task = []
}
this.task.push(execute.bind(this, id))
if(id === 4) {
for(let index = 0; index < this.task.length; index++) {
await this.task[index]()
}
}
}

for(var i = 0; i < 5; i++) {
start(i);
}

function sleep() {
const dur = Math.floor(Math.random() * 500);
return new Promise((res, rej) => {
setTimeout(() => {
res();
}, dur)
})
}

function execute(id) {
return sleep().then(() => {
console.log('id:' + id);
});
}