宏观和微观任务
JavaScript 引擎等待宿主环境分配宏观任务,在操作系统中,通常等待的行为都是一个事件循环,所以在 Node 术语中,也会把这个部分称为事件循环。
这里每次的执行过程,其实都是一个宏观任务。我们可以大概理解:宏观任务的队列就相当于事件循环。
在宏观任务中,JavaScript 的 Promise 还会产生异步代码,JavaScript 必须保证这些异步代码在一个宏观任务中完成,因此,每个宏观任务中又包含了一个微观任务队列:
Promise
Promise 是 JavaScript 语言提供的一种标准化的异步管理方式,它的总体思想是,需要进行 io、等待或者其它异步操作的函数,不返回真实结果,而返回一个“承诺”,函数的调用方可以在合适的时机,选择等待这个承诺兑现(通过 Promise 的 then 方法的回调)。
promise基本用法如下:
function sleep (duration) { return new Promise(function(resolve,reject){ setTimeout(resolve,duration); }) } sleep(1000).then(() => console.log('ok'))
这段代码定义了一个函数sleep 它的作用是等候传入参数指定时长。
promise的then回调是一个异步的执行过程。
var r = new Promise(function(resolve,reject){ console.log('a') resolve() }) r.then(() => console.log("c")) console.log("b")
打印出来的结果是abc/ 在进入c之前,对象r已经得到了resolve,但是promise为异步操作,所以c无法出现在b之前。
与setTimeout 一起执行promise
var r= new Promise(function (resolve,reject){ console.log("a") resolve() }) setTimeout(() => console.log("d"),0) r.then(() => console.log("c")) console.log("b")
得到的结果为abcd。为什么d在后面呢?
因为promise是JavaScript引擎内部的微任务,而setTimeout是游览器的api,它产生宏任务。
function sleep(duration){ return new Promise(function(resolve,reject){ console.log("b") setTimeout(resolve,duration) }) } console.log("a") sleep(5000).then(() => console.log("c"))
此段代码执行结果为abc
a先执行,结束之后promise执行,之后在五秒响应后又调用了resolve.然后c在执行。
async / await
async函数是一种特殊语法,特征是在function关键字之前加上async关键字,这样就定义了一个async函数,我们可以在其中使用await来等待一个promise。
function sleep (duration){ return new Promise(function(resolve,reject){ setTimeout(resolve,duration); }) } async function foo() { console.log("a") await sleep(2000) console.log("b") }
async函数强大在于它是可以嵌套的,可以利用async函数组合出新的async函数。
function sleep(duration){ return new Promise(function(resolve,reject){ setTimeout(resolve,duration) }) } async function foo(name){ await sleep(2000); console.log(name) } async function foo2() { await foo("a") await foo("b") }