# Promise (重点)

# 简介

  1. Promise对象代表一个异步操作,有三种状态:pending(进行中)、fulfilled(已成功)和rejected(已失败)
  2. 一旦状态改变,就不会再变。Promise对象的状态改变,只有两种可能:从pending变为fulfilled和从pending变为rejected
  3. 缺点:首先,无法取消Promise,一旦新建它就会立即执行,无法中途取消。其次,如果不设置回调函数,Promise内部抛出的错误,不会反应到外部。第三,当处于pending状态时,无法得知目前进展到哪一个阶段(刚刚开始还是即将完成)。

# 用法

const promise = new Promise(function(resolve, reject) {
  // ... some code
  if (/* 异步操作成功 */){
    resolve(value);
  } else {
    reject(error);
  }
});
promise.then(function(value) {
    //resolve 结果
  // success
}.catch(function(error) {
  //error  catch捕获异常
  console.log('发生错误!', error);
}).finally(()=>{
    //do something 不管状态如何都执行
})

Promise.all()和race() 用于多个Promise示例,包装成新的Promise示例

const p = Promise.all([p1, p2, p3]);
/**
1.只有p1、p2、p3的状态都变成fulfilled,p的状态才会变成fulfilled,此时p1、p2、p3的返回值组成一个数组,传递给p的回调函数。
2. 只要p1、p2、p3之中有一个被rejected,p的状态就变成rejected,此时第一个被reject的实例的返回值,会传递给p的回调函数。
*/
const race = Promise.race([p1, p2, p3]);
/**
只要p1、p2、p3之中有一个实例率先改变状态,p的状态就跟着改变。那个率先改变的 Promise 实例的返回值,就传递给p的回调函数。
*/

# Iterator

# 概念

遍历器(Iterator)是一种接口,为各种不同的数据结构提供统一的访问机制。任何数据结构只要部署 Iterator 接口,就可以完成遍历操作
Iterator的作用有三个:

  • 一是为各种数据结构,提供一个统一的、简便的访问接口;
  • 二是使得数据结构的成员能够按某种次序排列;
  • 三是 ES6 创造了一种新的遍历命令for...of循环,Iterator 接口主要供for...of消费。

原生具备 Iterator 接口的数据结构如下

  • Array
  • Map
  • Set
  • String
  • TypedArray
  • 函数的arguments对象
  • NodeList对象

调用Iterator接口的场合

  1. 解构赋值
  2. 扩展运算符...
  3. yield*,后面跟可遍历的结构,它会调用该结构的遍历器接口
  4. for...of
  5. Array.from()
  6. Promise.all(),Promise.race()
  7. Map(), Set(), WeakMap(), WeakSet()

# Generator

# 概念

Generator 函数是一个普通函数,但是有两个特征。一是,function关键字与函数名之间有一个星号;二是,函数体内部使用yield表达式,定义不同的内部状态,调用遍历器对象的next方法,使得指针移向下一个状态

# 用法

function* g() {
  yield 'hello';
  yield 'world';
  return 'ending';
}
var hw = g();
hw.next()
//{value:'hello',done:false}

返回一个遍历器,可以用for of 循环,...运算,解构

function* foo() {
  yield 1;
  yield 2;
  yield 3;
  return 6;
}
// 扩展运算符
[...foo()] // [1, 2,3]

// Array.from 方法
Array.from(foo()) // [1, 2,3]

// 解构赋值
let [x, y] = foo();
x // 1
y // 2
for (let v of foo()) {
  console.log(v);
}
// 1 2 3 

co模块 可以自动执行 Generator 函数

# async (重点)

# 含义

async 是Generator 函数的语法糖,把*换成async,yield 换成await,并且内置执行器,返回值是Promise对象
(python 也有差不多的语法 async await)

# 用法

// 函数声明
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 () => {};

# 错误处理

await后面的异步操作出错,那么等同于async函数返回的 Promise 对象被reject。

f()
.then(v => console.log(v))
.catch(e => console.log(e))
//放在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);
  }
}

# 多个并发

let [foo, bar] = await Promise.all([getFoo(), getBar()]);

asyncawait 相比直接使用 Promise 来说,优势在于处理 then 的调用链,能够更清晰准确的写出代码。缺点在于滥用 await 可能会导致性能问题,因为 await 会阻塞代码,也许之后的异步代码并不依赖于前者,但仍然需要等待前者完成,导致代码失去了并发性