promise
什么是promise
promise是异步编程的一种解决方案,从语法上来说,Promise是一个对象,从它可以获取异步操作的消息
ES6规定,Promise对象是一个构造函数,接受一个函数作为参数,这个函数会立即执行,该函数的两个参数分别是resolve和reject,它们是两个函数。
resolve函数的作用是将Promise对象的状态从Pending变成Resolved,在异步操作成功时调用并将异步操作结果作为参数传递出去;reject函数的作用是,将Promise对象的状态从Pending变成Rejected,在异步操作失败时调用,并将异步操作报出的错误作为参数传递出去。
promise实例生成后,可以用then方法指定成功后或失败后的回调函数
promise状态
- 待定(Pending):初始状态,当执行executor中的代码时处于该状态
- 已兑现(resolved/fulfilled):操作成功,执行了resolve时,处于该状态
- 已拒绝(rejected):意味着操作失败,执行了reject时,处于该状态
promise的特点
1.不受外界的影响。只有异步操作结果可以决定当前是哪一种状态,任何其他操作都无法改变这个状态。
2. 一旦状态改变就不会再变,任何时候都可以得到这个结果
promise的缺点
- 无法取消Promise,一旦新建它就会立即执行,无法中途取消。
- 不设置回调函数,promise内部抛出的错误不会反映到外部。
- 当处于Pending状态时,无法得知目前进展到哪一个阶段(刚刚开始,还是即将完成)
promise的方法
- then
- Promise实例具有then方法,then方法是定义在原型对象上的。
- then方法接受两个参数:第一个参数是fulfilled状态的回调函数,第二个参数是Rejected的回调函数
- then方法可以被多次调用,每次调用都会传入对应的fulfilled回调
- then方法返回的是一个新的Promise实例。因此可以采用链式写法。
then中return 的值决定新返回的promise的状态:
非promise:成功
promise:状态与该promise一致
抛出异常:失败
-
catch
用于发生错误时的回调函数
事实上catch方法也是会返回一个Promise对象的,所以catch方法后面我们可以继续调用then方法或catch方法。
promise对象的错误具有冒泡性质,会一直向后传递,直到被捕获为止 -
finally
finally方法用于不管Promise对象最后状态如何都会执行的操作。
他接受一个普通函数作为参数,该函数不管怎样都必须执行。 -
resolve
有时需要将现有对象转为Promise对象,Promise.resolve方法就起到了这个作用。
- 参数是一个Promise实例,那么Promise.resolve将不做任何修改,原封不动的返回实例
- 参数是一个thenable对象,Promise.resolve方法会将这个对象转为Promise对象,然后立即执行thenable对象的then方法.
- 参数不具有then方法的对象或根本不是对象或没有参数,那么Promise.resolve方法返回一个新的Promise对象,状态为Resolved
-
reject
Promise.reject方法会返回一个新的promise实例,状态为Rejected,无论参数是何形态
-
all
promise.all方法将多个Promise实例包装成一个新的Promise实例。如果不是Promise实例就会先调用Promise.resolve方法,将参数转换为Promise实例
promise.all方法的参数不一定是数组,但是必须具有Iterator接口- 当所有的Promise状态变成fulfilled状态时,新的promise状态才会变成fulfilled,并将所有Promise的返回值组成一个数组
- 当有一个Promise状态为rejected时,新的Promise状态为rejected,并且返回第一个rejected返回值作为参数
-
race
promise.race方法将多个Promise实例包装成一个新的Promise实例。
只要有一个实例先改变状态,新的promise状态就跟着改变,并返回率先改变的Promise实例的返回值作为参数
Iterator/for…of
什么是Iterator
它是一种接口,目的是为所有数据结构提供统一的访问机制,即for…of循环
Iterator遍历过程
- 创建一个指针对象,指向当前数据的起始位置
- 第一次调用指针对象的next方法,可以将指针指向数据结构的第一个成员。
- 不断调用指针对象的next方法,直到它指向数据结构的结束位置。
每次调用next方法都会返回数据结构的当前成员的信息。
具体返回一个包含value和done两个属性的对象。其中value属性是当前成员的值,done属性是一个布尔值,表示遍历是否结束。
原生具备Iterator接口的数据
String、Array、Map、Set、函数的arguments对象、NodeList对象
Iterator应用
JavaScript中语法:for …of、展开语法、yield*、解构赋值;
创建一些对象时:new Map([Iterable])、new WeakMap([iterable])、new Set([iterable])、new WeakSet([iterable]);
一些方法的调用:Promise.all(iterable)、Promise.race(iterable)、Array.from(iterable);
迭代器中断
迭代器在某些情况下会在没有完全迭代的情况下中断,比如遍历的过程中通过break、continue、return、throw中断了循环操作;
Iterator接口与Generator
Generator
什么是生成器
Generator函数是ES6提供的一种异步解决方案,执行Generator函数会返回一个遍历器对象,返回的遍历器对象。
形式上Generator函数是一个普通函数但是有两个特征:
- function关键字与函数名之间有一个星号(*)
- 函数体内部使用yield语句定义不同的内部状态(yield的意思是产出)
yield表达式
yield语句是暂停标志
yield只能在Generator函数里面,用在其他地方会报错
yield表达式如果用在另一个表达式中,必须放在圆括号里面
如果yield表达式后面跟的是一个遍历器对象,需要在yield表达式后面加上星号,表明它返回的是一个遍历器对象。这被称为yield*表达式。
遍历器对象的next方法的运行逻辑如下。
- 遇到yield语句就暂停执行后面的操作,并将紧跟在yield后的表达式的值作为返回对象的value值。
- 下一次调用next方法时再继续往下执行,直到遇到下一条yield语句。
3.如果没有再遇到新的yield语句,就一直到函数结束,直到return语句为止,并将return语句后面的表达式值作为返回对象的value属性值 - 如果该函数没有return语句,则返回对象的value属性值为undefined
yield和return的异同
- 都能返回紧跟在语句后面的那个表达式的值
- 每次遇到yield,函数暂停执行,下一次再从该位置继续向后执行,return语句不具备位置记忆功能
- 一个函数里面只能执行一次return语句,但可以执行多次yield表达式
next方法参数
yield表达式本身没有返回值,或者说总是返回undefined,next方法可以带一个参数,该参数会被当作 【上一个yield表达式】的返回值,所以第一次使用next方法时传递参数是无效的。
Generator.prototype.throw()
Generator函数返回的遍历器对象,都有一个throw方法,可以在函数体外抛出错误,然后在Generator函数体内捕获。
Generator.prototype.return()
Generator函数的遍历器对象中还有一个return方法,可以返回给定的值,并且终结遍历Generator函数。
for…of循环
for…of循环可以自动遍历Generator函数运行时生成的Iterator对象,不需要调用next方法(不包括return语句)
for…of与for…in的区别
- for-in适合遍历对象属性,for-of适合遍历数组
- for…in 循环:只能获取对象的键名,不能获得键值;for…of循环:允许便利获得键值。
- for…in循环可以可枚举的属性,for…of遍历的是可迭代的
- for-of不能直接遍历普通的对象,需要通过Object.keys()搭配使用
async/await
async是什么
用一句话来说,他就是Generator函数的语法。
async函数就是将Generator函数的星号换成async,将yield换成了await
async对Generator函数的改进
- 内置执行器
Generator函数的执行必须依靠执行器,所以才有了co模块,而async自带执行器 - 更好的语义
async表示函数里有异步操作,await表示紧跟在后面的表达式需要等待结果。 - 更广的适用性
co模块约定,yield命令后面只能是Thunk函数或Promise对象,而async函数的await命令后面,可以是Promise对象和原始类型的值(数值、字符串和布尔值,但这时等同于同步操作) - 返回值是Promise
async函数的返回值是Promise,比Generator函数的返回值是Iterator对象方便了许多。可以用then方法指定下一步的操作
进一步说async函数完全可以看作由多个异步操作包装成的一个Promise对象,而await命令就是内部then命令的语法糖
async语法
- async函数返回一个Promise对象,async函数内部return语句返回的值,会成为then方法回调函数的参数。
- async函数返回的Promise对象必须等到内部所有await命令后面的Promise对象执行完成后才会发生状态改变,除非遇到return语句或者抛出错误。
await命令
- 正常情况下,await命令后面是一个Promise对象。如果不是,会被转成一个立即resolve的Promise。
- 只要一个await语句后面的Promise变成reject,那么整个async函数都会中断执行
- 如果await后面的异步操作出错,那么等同于async函数返回的Promise对象被reject
回调地狱
为了能够拿到异步的数据,使用了大量的回调函数,来获取将来异步执行成功之后的数据。使得代码更加难以理解和维护。