JianShaw / note

记录个人学习
2 stars 0 forks source link

更方便的异步操作方式-async 函数 #2

Open JianShaw opened 7 years ago

JianShaw commented 7 years ago

ES2017 标准引入了 async 函数,使得异步操作变得更加方便。

写一个简单的实现

var wait = time => {
  return new Promise((resolve,reject)=>{
     setTimeout(()=>{
       console.log(`执行${time}`)
       resolve();
     },time)
  })
}

var start = async function(){
  console.log(`执行start`)
  await wait(3000);
  await wait(5000);
  await wait(4000);
}
start()

node中执行node --harmony-async-await *.js

//依次输出
执行start
3000
5000
4000

async函数返回一个 Promise 对象,可以使用then方法添加回调函数。当函数执行的时候,一旦遇到await就会先返回,等到异步操作完成,再接着执行函数体内后面的语句。

var getMsg = time => {
  return new Promise((resolve,reject)=>{
     setTimeout(()=>{
       console.log(`等待${time}`)
       resolve(`return msg....${time}`);
     },time)
  })
}

async function foo(){
  let msg1 = await getMsg(2000);
  let msg = await getMsg(5000);
  return msg //  或者是一个promise对象
}
foo().then(data => console.log(data))
//输出
等待2000
等待5000
return msg....5000

如果async函数内部发生错误,promise对象会变成reject状态,抛出的错误会被catch回掉方法捕捉到

async function f() {
  throw new Error('出错了11111');
}
f().then(
  v => console.log(v),
  e => console.log(e)
)

同下边的代码一样都会捕捉到错误

f().then(v => console.log(v)).catch(err=>console.log(err))

async函数返回的 Promise 对象,必须等到内部所有await命令后面的 Promise 对象执行完,才会发生状态改变,除非遇到return语句或者抛出错误。也就是说,只有async函数内部的异步操作执行完,才会执行then方法指定的回调函数。

await

正常情况下,await命令后面是一个 Promise 对象。如果不是,会被转成一个立即resolve的 Promise 对象。(很好理解,不做过多说明)

var error = info => {
  console.log(info)
  return Promise.reject(info)
}
var success = info => {
  console.log(info)
  return Promise.resolve(info)
}

(async function(){
  try{
    await error('error msg')
  }catch(e){
  }
  await success('success')
})()

另一种写法

var error = info => {
  console.log(info)
  return Promise.reject(info)
}
var success = info => {
  console.log(info)
  return Promise.resolve(info)
}

(async function(){
    await error('error msg').catch(err=>console.log(err));
    await success('success')
})()

注意:多个await命令后面的异步操作,如果不存在继发关系,最好让它们同时触发。

// 多个继发关系的demo
var getMsg = time => {
  return new Promise((resolve,reject)=>{
     setTimeout(()=>{
       console.log(`等待${time}`)
       resolve(`return msg....${time}`);
     },time)
  })
}

(async function foo(){
  var data = await Promise.all([getMsg(500),getMsg(700)]);
  console.log(data)
})()

下边的例子执行效果如上

var getMsg = time => {
  return new Promise((resolve,reject)=>{
     setTimeout(()=>{
       console.log(`等待${time}`)
       resolve(`return msg....${time}`);
     },time)
  })
}

(async function foo(){
  // 写法二
let getMsg500 = getMsg(500);
let getMsg700 = getMsg(700);
let foo = await getMsg500;
let bar = await getMsg700;
console.log(foo,bar)

})()

async函数的多种实现方式

// 函数声明
async function foo() {}

// 函数表达式
const foo = async function () {};

// 对象的方法
let obj = { async foo() {} };
obj.foo().then(...)

// Class 的方法
class Storage {
  constructor() {
    this.cachePromise = caches.open('avatars');
  }

  async getAvatar(name) {
    const cache = await this.cachePromise;
    return cache.match(`/avatars/${name}.jpg`);
  }
}

const storage = new Storage();
storage.getAvatar('jake').then(…);

// 箭头函数
const foo = async () => {};

相关文档