在 javascript 面试中对异步的理解

异步概念

对于 js 不知道异步是什么,为什么需要有异步的同学来说,可以先看看我的这篇文章 如错误之处,请求指点,谢谢阅读。


异步进一步理解

对于已经了解了异步的基本概念的同学,我们可以来看一下,下面的这个例子,有助于我们更好的理解异步(注意chrom: 版本:72.0.3626.121 版本不同结果有点差异)
复制代码
// 今日头条面试题
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')
})
async1()
new Promise(function (resolve) {
   console.log('promise1')
   resolve()
}).then(function () {
   console.log('promise2')
})
console.log('script end')

// result:
// script start
// async1 start
// async2
// promise1
// script end
// async1 end
// promise2
// settimeout
复制代码

执行过程的分析:

  1. 遇到 console.log('script start'), 放在主线程中立即执行,所以第一步先输出 script start
  2. 遇到 setTimeout,因为 setTimeout 是异步的,所以将回调函数放入异步队列中去等待,等待主线程中的任务执行完之后,再通过事件轮询的方式去调用
  3. 遇到 async1 函数的调用,此时走到 async1 函数里面输出 async1 start
  4. 遇到 await 关键字,进入到 async2 函数中输出 async2,将 await 后面的代码放入微任务中,执行后面的操作
  5. 遇到 Promise 直接输出promise1,将回调函数放入微任务中,执行后面的操作
  6. 遇到 console.log('script end'), 放在主线程中立即执行,所以第一步先输出 script end,到这个时候主线程中的代码就执行完了
  7. 主线程中的代码执行完之后,立即执行所有的微任务。分别输出 async1 end,promise2
  8. 最后通过事件轮询的方式将异步队列中代码,拿到主线程中来执行 (输出 settimeout)
  9. 重复步骤8

注意

  • await 关键字必须在用 async 关键字修饰的函数中才能使用。
  • async 语法其实也就是 Promise 语法。

上面例子中的这部分代码可以转化为:

转化前:

    async function async1() {
       console.log('async1 start')
       await async2()
       console.log('async1 end')
    }
复制代码

转化后:

    async function async1() {
       console.log('async1 start')
       new Promise((resolve, reject) => {
           this.async2()
           resolve()
       })
       .then(body => {
           console.log('async1 end')
       })
    }
复制代码

为了巩固大家可以练下下面两个题目:

async function async1() {
    console.log('async1 start');
    await async2();
    setTimeout(function() {
        console.log('setTimeout1')
    },0)
}
async function async2() {
	setTimeout(function() {
		console.log('setTimeout2')
	},0)
}
console.log('script start');

setTimeout(function() {
    console.log('setTimeout3');
}, 0)
async1();

new Promise(function(resolve) {
    console.log('promise1');
    resolve();
}).then(function() {
    console.log('promise2');
});
console.log('script end');
复制代码
async function async1() {
   console.log('async1 start')
   await async2()
   console.log('async1 end')
}
async function async2() {
   console.log('async2')
	new Promise((resolve, reject) => {
		console.log('promise3')
		resolve()
	})
	.then(body => {
		console.log('promise4')
	})
}
console.log('script start')
setTimeout(function () {
   console.log('settimeout')
})
async1()
new Promise(function (resolve) {
   console.log('promise1')
   resolve()
}).then(function () {
   console.log('promise2')
})
console.log('script end')
复制代码

答案:

    script start
    async1 start
    promise1
    script end
    promise2
    setTimeout3
    setTimeout2
    setTimeout1
复制代码
    script start
    async1 start
    async2
    promise3
    promise1
    script end
    promise4
    async1 end
    promise2
    settimeout
复制代码

谢谢大家的阅读,不对之处,请指教。

转载于:https://juejin.im/post/5c85d75b6fb9a049ac79fc58

你可能感兴趣的:(在 javascript 面试中对异步的理解)