异步操作 async 函数(async、await)

207 阅读3分钟

async关键字

async是es7中出现的一个与异步操作相关的关键字,用来标识声明一个函数为异步函数。被标识过的函数将会返回一个Promise对象(所以这个函数将具备then方法)。 注意:async函数一定会返回一个promise对象,就算函数中return后的不是一个promise对象、也会隐身转换成一个promise对象。

async function myAsyncasync(){ return 'there is a async function' }

测试如下 // async function 将返回一个Promise对象

async function myAsync(){
    return '这是一个异步函数' // 这里return的是一个直接量也会被转成promise对象
}
async function myAsync1(){
    return new Promise((resolve, reject)=>{
        resolve(12306)
    })
}
const result = myAsync()
const result1 = myAsync1()

console.log(result, result instanceof Promise)
result.then((data)=> {
    console.log('async函数中return的是非promise时',data)
})
result1.then((data)=> {
    console.log('async函数中return的是promise时', data)
})

我晕 公司上传不了运行代码截图 (这里假装有 )。

await关键字

async 声明过异步函数后就要在函数内部进行或者等待异步操作了,await关键字从字面意思正是“等待”,语法上 await 关键字只能出现在async 标识的async函数内部否则将会报错当然也没有意义、await 表达式 用来接收等待的结果而不是等待处理本身 (如接收的时一个promise处理结果返回值 而不是promise对象):

async function myAsync2(){
  const res = await new Promise((resolve, reject)=>{
        resolve(12306)
    })
  console.log('结果res', res)
}
myAsync2()

这里将会输出 ‘结果res 12306’ 另外,值得注意的是async 函数中也可以不出现 await 只不过没有了"await"等待就和普通函数一样立即执行了 也就名不符实了 当然await关键字后直接是一个值也是可以的 只不过是个假等待而已

async function myAsync2(){
  const res = await 1110
  console.log('结果res', res)
}
myAsync2()

更加深入一下await到底做了什么、上面说到async 函数会返回一个promise对象 而它内部await 关键字标识的语句正是在等待这个promise对象的执行并将这个promise对象的结果拿到。

async function myAsync(){
    console.log('script 1 ')
    const res = await 3 // 这里相当于 new Promise((resolve, reject)=> { resolve(3) }) 而await等待后的 console.log('script 3') 这一句就相当promise后上的then上执行了
    console.log('script 3')
}

这意味个 await 做了类似这么一个过程 将await 表达式 构建了一个promise 在执行器函数中做一些具体的逻辑处理 然后执行 resolve 或 reject 所以 回到async函数体中 await(res = await ...) 后面的操作相当于 是在执行 promise.then() 了

那么以下代码执行顺序将会是怎么?

async function async1(){
    console.log('async1 start')
    await test() // 这里走的 相当于 promise resolve之前的执行代码
    console.log('async1 end') // 这里相当是 promise resolve() 后then执行的 (promise.then 微任务)
}
function test(){
    console.log('test 1')
    new Promise((resolve, reject)=>{
        console.log('test2')
        resolve()
    }).then(()=>{
        console.log('test')
    })
}
setTimeout(()=>{
    console.log('setTimeout')
}, 0)
console.log('script start') 
console.log('script end')
async1() 

打印结果:

script start -> script end -> async1 start -> test1 -> test 2 -> test -> async1 end -> setTimeout

解释以下 事件循环开始:script start(当前宏) -> script end (当前宏)-> async1 start(当前宏) -> test1(当前宏) -> (异步队列执行、下一个宏任务前先清空 microtask quene )test 2(microtask) -> test (microtask)-> async1 end (microtask) -> setTimeout(macrotask)

相关介绍:事件循环、宏任务、微任务