promise & async 学习笔记

182 阅读3分钟

promise and async

js设计初衷是应用于浏览器端,为了避免用户交互时候的冲突,js是单线程的,为了解决js中的很多异步场景的问题。

//最常见的一种回调的嵌套:---回调地狱
doAsyncJob1(function(){
doAsyncJob2(function(){
    doAsyncJob3(function(){
        doAsyncJob4(function(){
            //Black hole    
        });
    })    
   });
 });

es6以及之后提案提出了几个解决方案。以下是对这几个异步解决方案的简单理解。

promise

promise 类似于不可逆的状态机。只能pengding到fulfilled或者到rejected。

const promise = new Promise(function(resolve, reject) {
  // ... some code
  if (/* 异步操作成功 */){
    resolve(value);
  } else {
    reject(error);
  }
});
promise.then(function(value){
    console.log(value)
},function(error){
    console.log(error)
})

关键点

  1. resolve 和 reject为内置函数,then函数内部是回调函数(可分别接受resolve和reject的回调),resolve和reject可以分别传参给这两个函数。
  2. 举一个可以解决请求的回调嵌套的例子
const p1 = new Promise(function(resolve,reject){
    ....
})
const p2 = new Promise(function(resolve,reject){
    resolve(p1)
})

  1. p2的执行依赖于p1的执行结果。
  2. resolve或者reject并不会阻止promise内部剩余其他代码的执行。
  3. promise.then返回一个新的promise对象,可以链式调用。像二中的代码可以写成promise.then().then().then()...的形式。
  4. 错误处理(reject状态处理),catch方法里处理更加推荐(语义化)。
// bad
promise
  .then(function(data) {
    // success
  }, function(err) {
    // error
  });

// good
promise
  .then(function(data) { //cb
    // success
  })
  .catch(function(err) {
    // error
  });
  1. 另外还有两个很有用的方法:
//promise.all:所有请求同时发送,都成功之后resolve。
// 多个请求可以同时处理时候性能提升显著
promise.all([p1,p2,p3],function{
    
})
// 第一个成功之后resolve,并且回调函数返回一个基于该成功的promise对象。
promise.race

不足之处

  1. 一旦开始无法结束
  2. 会吃掉错误,如果没有相应回调来处理错误,promise错误不会传递到外层。

async

async 是js实现异步的另一种方式,本质上是generate函数的语法糖。 它返回一个promise对象,可以调用then方法对返回的内容进行处理。gennerate需要手动调用一个指向内部的指针,来进行异步操作(详见),而async则不用。

// 
const asyncReadFile = async function () {
  const f1 = await readFile('/etc/fstab');//等我执行完
  const f2 = await readFile('/etc/shells');//等我也执行完再打印
  console.log(f1.toString());
  console.log(f2.toString());
};

函数内部await引导的异步操作会同步执行。async函数返回一个promise对象,可以使用then对返回值进行处理,错误处理也同promise。

await命令

await命令后边是一个promise对象,如果不是那就会被转化成一个状态为resolve的promise对象。

错误处理以及使用注意

async function f() {
  await Promise.reject('出错了');
  await Promise.resolve('hello world'); // 不会执行
}

解决办法:

  1. 在内部catch(err);
async function f() {
  await Promise.reject('出错了')
    .catch(e => console.log(e));
  return await Promise.resolve('hello world');
}

f()
.then(v => console.log(v))
// 出错了
// hello world
  1. 可能reject的代码写在try,catch中。
async function main() {
  try {
    const val1 = await firstStep();
    const val2 = await secondStep(val1);
    const val3 = await thirdStep(val1, val2);

    console.log('Final: ', val3);
  }
  catch (err) {
    console.error(err);
  }
}
  1. 灵活应用promise.all进行并行处理,提升性能