fun([
() => console.log('start'),
() => sleep(1000),
() => console.log('1'),
() => sleep(2000),
() => console.log('2'),
() => sleep(3000),
() => console.log('end'),
]);
根据以上代码,补齐fun
和sleep
函数,使得fun
执行后打印结果为:start -> 1s后输出1 -> 2s后输出2 -> 3s后输出end
思路
这题考察的就是对Promise
已经async
和await
的使用。因为按照题目可以知道要让函数顺序执行,并且没有执行完就阻塞后续代码执行,而async
和await
正好可以做到将函数内部变为同步执行。
已经知道console.log是同步的了,那么需要将sleep函数变为可以阻塞后续代码执行的函数就完成了
实现
1、将fun函数包装为异步函数
因为要使fun函数内为同步执行,要配合await
使用则函数得加上async
关键字
2、使用Promise将sleep函数变为异步函数
// 将延迟的时间作为参数传入
function sleep(time) {
// 返回一个Promise,将函数变为异步函数
return new Promise(resolve => {
// time秒后执行回调
setTimeout(resolve, time);
});
}
众所周知,await
可以用来等待一个函数的执行结果,前提是该函数必须返回的是一个Promise。await
是一个语法糖。不使用await
时,我们想要在一个不确定情况下同步获得结果,可能是这样写:
// 例如获取数据不知道要多久,假定为3s
function getData() {
return new Promise(resolve => {
setTimeout(() => {
resolve('data');
}, 3000);
});
}
// 获取数据后我们要进行操作,比如输出,我们会这样写
getData().then(res => {
console.log(res);
});
而有了async
和await
语法糖后我们就能这样写:
async function getList() {
const data = await getdata();
console.log(data);
}
getList(); // 3s后输出data
这就是语法糖的效果,将一个函数包装为异步函数,里面可以使用await
用来等待函数执行完毕,并且会阻塞后面console.log的执行。所以答案已经出来了:
function sleep(time) {
return new Promise(resolve => {
setTimeout(resolve, time);
});
}
async function fun(fns) {
let len = fns.length;
for (let i = 0; i < len; i++) {
await fns[i]();
}
}
// 或
async function fun(fns) {
let len = fns.length;
let index = 0;
while (index < len) {
await fns[index]();
index++;
}
}
注意:fun函数中循环不能使用forEach,因为fun函数作为一个包装函数,将其体内的代码执行变为同步;但是使用forEach后,本质上变成了一个函数内执行了多个异步回调(forEach(item => {})),所以就不能保证里面是按顺序执行了