Async全解

async function

  • async关键字声明或者使用异步函数表达式
  • 隐式的返回Promise结果,成功执行resolve,抛出异常执行reject
  • 函数体可使用await关键字暂停函数执行,等待promise,然后继续执行

Syntax

async function name([param[, param[, ... param]]]) { statements }

Example

function resolveAfter2Seconds() {
  return new Promise(resolve => {
    setTimeout(() => {
      resolve('resolved');
    }, 2000);
  });
}

// 声明一个异步函数
async function asyncCall() {
  console.log('calling');
  const result = await resolveAfter2Seconds();
  console.log(result);
  return !Math.ceil(Math.random() - 0.5) ? true : Promise.reject(false)
}

// 使用函数表达式
const asyncExpressFunc = async (promise) => {
    let result
    try{ 
        result = await promise
    } catch(err) {
        result = err
    }
    return result
}

asyncCall().then(promise => {
    return asyncExpressFunc(promise)
}).then((resolved) => {
    console.log(resolved, 'from asyncExpressFunc')
}).catch((rejected) => {
    console.log(rejected, 'from asyncExpressFunc')
})

await

  • await Promise
  • await Thenable objects
  • 和for搭配使用
  • 与一些内置对象的方法一起使用(方法前加关键词async)

await Promise

async function awaitPromise() {
    await new Promise(resolve => {
    setTimeout(() => {
      resolve(x);
    }, 2000);
  })
}

await Thenale Object

async function awaitThenable() {
  const thenableObj= {
    then: function(resolve, _reject) {
      setTimeout(() => {
          resolve(1)
      }, 2000)
    }
  }
  console.log(await thenableObj)
}

与for一起使用

async function asyncFor() {
    for (let i = 0; i < 4; i++) {
        const result = await new Promise((resolve) => {
            setTimeout(() => {
                resolve(i ** 2)
            }, 1000)
        })
        console.log(result)
    }
}
  • 并发,eslint建议写法
async function asyncConcurrencyFor() {
    const results = []
    for (let i = 0; i < 4; i++) {
        const result = new Promise((resolve) => {
            setTimeout(() => {
                resolve(i ** 2)
            }, 1000)
        })
        results.push(result)
    }
    await Promise.all(results).then(res => {
        console.log(res)
    })
}
  • for await...of, 与内置 String, Array, ArrayLike objects (e.g., arguments or NodeList), TypedArray, Map, Set和自定义Iterable使用

-

-

-

-

-

async function asyncForawait() {
    const awaitArrs = [
        Promise.resolve(1),
        2,
        Promise.reject(3),
        Promise.resolve(4),
        Promise.reject(5),
    ]
    try {
        for await (let item of awaitArrs) {
            console.log(item)
        }
    } catch(err) {
        console.log(err)
    }   
}

抛出的异常会中断循环

const asyncIterable = {
  [Symbol.asyncIterator]() {
    return {
      i: 0,
      next() {
        if (this.i < 3) {
          return Promise.resolve({ value: this.i++, done: false })
        }
        return Promise.resolve({ done: true })
      }
    }
  }
}

async function asyncForIterable() {
   for await (let num of asyncIterable) {
     console.log(num)
   }
}
  • 在async generator函数中使用
async function* asyncGenerator() {
  let i = 0;
  while (i < 3) {
    yield i++;
  }
}

async function asyncForGenerator() {
  for await (let num of asyncGenerator()) {
    console.log(num);
  }
}

AsyncFunction

  • 用来创建异步函数,JavaScript 中每个异步函数都是 AsyncFunction 的对象
  • AsyncFunction 并不是一个全局对象,需要通过 Object.getPrototypeOf(async function(){}).constructor 来获取

Syntax

new AsyncFunction([arg1[, arg2[, ...argN]],] functionBody)

通过 AsyncFunction 构造器创建一个异步函数

function resolveAfter2Seconds(x) {
  return new Promise(resolve => {
    setTimeout(() => {
      resolve(x);
    }, 2000);
  });
}

const AsyncFunction = Object.getPrototypeOf(async function(){}).constructor;
const a = new AsyncFunction('a', 'b', 'return await resolveAfter2Seconds(a) + await resolveAfter2Seconds(b);');
a(10, 20).then(v => {
  console.log(v); // 4 秒后打印 30
});

不建议使用AsyncFunction,因为还得通过async function去拿AsyncFunction

async function实现原理

  • Promise + Generator
  • 默认返回promise
  • 抛出异常处理
  • await -> yield等待promise执行

模拟实现:

export const generatorRun = (genFunc) => {
    return new Promise((resolve, reject) => {
        const gen = genFunc()
        const step = (nextF) => {
            let next
            try {
                next = nextF()
            } catch (e) {
                return reject(e)
            }
            if (next.done) {
                return resolve(next.value)
            }
            Promise.resolve(next.value).then((v) => {
                step(() => {
                    return gen.next(v)
                })
            }, (e) => {
                step(() => {
                    return gen.throw(e)
                })
            })
        }
        step(() => {
            return gen.next(undefined)
        })
    })
}

console结果可能不准确,按F12打开控制台查看