每日一题 异步

131 阅读1分钟

以下的题来自 高级前端进阶博文 | 木易杨前端进阶 (muyiy.cn)

1. setTimeout、Promise、Async/Await 的区别

  • setTimeout 的回调函数会放到宏任务队列中,等到执行栈清空之后执行

  • Promise 本身是同步的任务会立即执行,Promise.then里的函数会放到微任务队列中,宏任务里面的同步代码执行完毕之后执行

  • Async/Await async函数表示里面可能有异步方法,返回一个Promise对象

    await 后面跟一个表达式,aync函数执行的时候遇到await后会立即执行表达式,然后把表达式后边的代码放进微任务队列中

2. Async/Await 如何通过同步的方式实现异步

Async/Await 实质是一个它就是 Generator 函数的语法糖(自执行的Generator函数),如下

function run(fn){
  const g = fn()
  function step(data){
    const res = g.next(data);
    if (res.done) return res.value;
    res.value.then(function(data){
      step(data);
    });
  }
  step();
}
run(gen)

3. 异步笔试题,请写出下面代码的运行结果

async function async1() {
    console.log('async1 start');
    await async2();
    console.log('async1 end');
}
async function async2() {
    console.log('async2');
}
console.log('script start');
setTimeout(function() {
    console.log('setTimeout');
}, 0)
async1();
new Promise(function(resolve) {
    console.log('promise1');
    resolve();
}).then(function() {
    console.log('promise2');
});
console.log('script end');

script start -> async1 start -> async2 -> promise1 -> script end -> async1 end -> promise2 -> setTimeout

image.png

4. 设计并实现 Promise.race()

Promise.race = (promises) => {
  return new Promise((resolve, reject) => {
    promises.forEach((promise) => {
      Promise.resolve(promise).then(resolve, reject);
    });
  });
};
function fn1 () {
  return new Promise((resolve, reject) => {
    setTimeout(()=>{
      reject('fn1')
    },700)
  })
}
function fn2 () {
  return new Promise((resolve, reject) => {
    setTimeout(()=>{
      resolve('fn2')
    },600)
  })
}
Promise.race([fn1(),fn2()]).then(r=>{
  console.log(r) //fn1
},err=>{
  console.log(err)
})

5. 设计并实现 Promise.all()

Promise.all = (promises)=>{
  return new Promise((resolve, reject)=>{
    let len = promises.length
    let res = new Array(len)
    let counts = 0
    for (const [idx,p] of promises.entries()) {
      Promise.resolve(p).then(r=>{
        counts++
        res[idx] = r
        if(counts===len){
          resolve(res)
        }
      },err=>{
        reject(err)
      })
    }
  })
}
function fn1  () {
  return new Promise((resolve,reject)=>{
      setTimeout(()=>{
        resolve(500);
      },500)
  })
}
function fn2  () {
  return new Promise((resolve,reject)=>{
      setTimeout(()=>{
        resolve(600);
      },600)
  })
}
Promise.all([fn1(),fn2()]).then(r=>{
  console.log(r)
},err=>{
  console.log(err)
})