随手笔记15-关于Promise-iterator-generator-async(ES6中解决异步编程的方案)

这里是参考阮一峰大牛编写的《ECMAScript 6 入门教程》进行部分总结

一、promise对象

1、Promise 的含义

Promise 是异步编程的一种解决方案,比传统的解决方案——回调函数和事件——更合理和更强大

2. 创建promise对象

创建promise对象时,需要传递一个函数作为参数,作为参数需要传递两个回调函数,resolve、reject作为参数,这两个参数可以被调用
resolve成功时的回调函数
reject失败时的回调函数

const promise = new Promise(function(resolve, reject) {
  // ... some code

  if (/* 异步操作成功 */){
    resolve(value);
  } else {
    reject(error);
  }
});

3. promise被创建完毕之后,会立即执行

let promise = new Promise(function(resolve, reject) {
  console.log('Promise');
  resolve();
});

promise.then(function() {
  console.log('resolved.');
});

console.log('Hi!');

// Promise
// Hi!
// resolved

4. Promise有三种状态

进行中 pending
成功 fullfilled
失败 rejected
pending----->成功 主动调用resolve
pending---->失败 主动调用reject方法

5.then(然后)方法

then方法可以接收两个参数,这两个参数都是函数,
第一个参数(函数):成功时的回调
第二个参数(函数):失败时的回调

then方法默认会返回一个新的promise对象

6.catch(捕获)方法

能够接收一个失败的回调(参数是一个函数,promise状态失败时,会触发这个函数)

7.接收失败信息

根据以上两点可以总结出两种接收失败信息的方法
方法一:使用then方法的第二个参数
方法二:使用catch方法的参数
catch可以捕获到代码中的异常

推荐使用catch来接收失败的信息

8.链式调用

p.then().then().then()…

then方法的第一个参数,成功时的回调函数,分两种情况:
第一种情况:返回了一个普通的数据(非promise),这个值会作为参数传递给下一个then的成功回调
第二种情况:返回了一个promise,下一个then的执行,取决于这个promise状态的改变

二、iterator(迭代器、遍历器)

1. 概念和作用

它是一种接口,为各种不同的数据结构提供统一的访问机制。任何数据结构只要部署 Iterator 接口,就可以完成遍历操作(即依次处理该数据结构的所有成员)。

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

iterator用来遍历集合类型,集合类型有:Array,Object,Set,Map
Array,Set和Map可以使用forEach来遍历(系统部署了iterator接口,所有可以用for…of…遍历)
Object使用for…in来遍历

2. 部署iterator接口

实际使用使用,需要在数据结构上部署默认的iterator接口;然后再通过next调用来使用。

在对象上部署iterator接口,如下例:
Array,Set和Map都默认具备iterator接口,默认接口叫做 Symbol.iterator

 // 我们以对象为例,来给对象部署默认iterator接口
let obj = { name: "zhangsan", age: 22, address: "北京" };
// 部署默认接口 Symbol.iterator ;用来访问不同的数据接口,真正实现iterator的功效
obj[Symbol.iterator] = function () {
    let keys = Object.keys(this); //[name,age,address]
    let index = 0; //记录索引下标

    return {
        // 箭头函数
        next: () => {
            if (index < keys.length) {
                let key = keys[index++];
                return { value: this[key], done: false };
            } else {
                return { value: undefined, done: true };
            }
        }
    };
};
// 访问默认的接口内容
let iterator = obj[Symbol.iterator]();
console.log(iterator.next());
console.log(iterator.next());
console.log(iterator.next());
console.log(iterator.next());//undefined

总结:
1、过程:创建的是一个指针对象,这个对象指向的是结构中的起始位置,也就是说interator本质上就是一个指针对象,通过调用next(),第一次调用指向的是结构中的第一个成员,第二次调用指向就是结构中的第二个成员,一直到结构结束的位置;

2、返回值:返回的是对象,{value:值,done:false} done为false的时候,表示可以继续循环遍历,为true表示遍历结束{value:undefined,done:true}

3.for…of的使用

for…of是iterator的语法糖,所以部署了iterator接口的数据集合都可以使用for…of遍历

  • for…of相比forEach和for…in的优势在哪里:
    1、无法中途跳出forEach循环,break命令或return命令都不能奏效。
    2、数组的键名是数字,但是for…in循环是以字符串作为键名“0”、“1”、“2”等等。
    for…in循环不仅遍历数字键名,还会遍历手动添加的其他键,甚至包括原型链上的键。不安全
    3、某些情况下,for…in循环会以任意顺序遍历键名。

总结:for…of适合遍历数组,for…in适合遍历对象

三、generator(生成器)

generator是一个函数,只不过这个函数的写法比较特殊,在function关键字和函数名之间有一个 * ,这样就构成一个generator生成器;
它不是普通的函数,它的调用不会立即执行;
调用后返回一个iterator遍历器,每次调用next则执行一步,直到调用结束。
return的返回可以立即结束iterator遍历器。

1. generator意义是什么?

generator内部是一个状态机,可以使用next调用返回多次结果;
也可以使用next传递参数给generator函数,来改变函数内部的执行逻辑。

generator内部支持yield表达式
,通过调用next,可以让generator内部的yield表达式执行;调用一次执行一次。
需要注意的是yield表达式没有返回值(返回undefined);
所以下一步的执行需要上一步执行结果的时候,可以使用next传递参数,如下:

function* pow(num) {
     let first = yield Math.pow(num, 2);
     let second = yield Math.pow(first, 2);
     return Math.pow(second, 2);
 }
 let iterator = pow(2);

 let { value: first } = iterator.next();
 console.log(first);

 let { value: second } = iterator.next(first);
 console.log(second);

 let { value: third } = iterator.next(second);
 console.log(third);

注意:
此时使用for…of不合适,因为没法传递参数

 for (let iterator of pow(2)) {
	console.log(iterator);
 }

四、async和await(重点)

ES6在2017年引入async函数,能够使异步操作更加方便
async函数就是Generator函数的语法糖
async函数就是将Generator函数中*替换为async

使用await替代yield async …await就是基于promise的generator函数和yield的语法糖

1. async函数

  1. async是用来修饰函数
  2. async修饰函数是异步函数
  3. async函数的返回值是一个promise对象
  4. 该函数内部的return结果,会作为函数调用promise对象的resolve结果

2. await

  1. await必须要出现在async修饰的方法中,否则报错,也就说await不能单独使用
  2. await用来等待一个方法的执行,该方法可以是同步方法也可以是promise,一般用来等待promise的执行
  3. 通过使用async…await可以让以前的then或catch回调函数形式,变成同步的做法,让可读性更好
  4. await等待的是promise的resolve结果,如果promise的结果是reject,await会报错,它处理不了异常;需要借助try…catch或catch来捕获异常
  5. 不管promise是成功还是失败,await都会等待这个异步处理,只有当异步有成功或失败的结果,才执行后续代码

3. await-to-js

await to用来捕获异常信息,处理异常,因为使用try…catch的方式来处理异常不能直接指导报错的是那一句代码,使用后缀加catch的方法使得代码不优雅

function to(promise) {
     return promise
         .then(rst => {
         	//在ES6中只返回一句代码,return和大括号都可以省略
         	//这里就不做省略了,增加可读性
             return [null, rst];
         })
         .catch(err => {
             return [err,null];
         });
 }

备注:
上述代码的then和catch都有return返回,下一次的链式进入then还是进入catch?

这需要看return 的内容是否有异常或是否是错误;比如return [null,rst]或 return [err,null] ,下一次都会进入then;比如:throw new Error(‘错误’),下一次会进去catch

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

一个爱编程的男孩

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值