1.Promise
Promise 是异步编程的⼀种解决⽅案,⽐传统的解决⽅案——回调函数和事件——更合理和更强⼤。 ⼀个 Promise 必然处于以下⼏种状态之⼀:
待定(pending): 初始状态,既没有被兑现,也没有被拒绝。
已兑现(fulfilled): 意味着操作成功完成。
已拒绝(rejected): 意味着操作失败
图源MDNPromise - JavaScript | MDN
1. 构造函数
创建⼀个新的 Promise 对象。该构造函数主要⽤于包装还没有添加 promise ⽀持的函数。 Promise 的实现会⽴即执⾏ executor ,并传⼊ resolve 和 reject 函数 。 resolve 函数的作⽤是将 Promise 对象的状态从“未完成”变为“成功”(即从 pending 变为 resolved),在异步操作成功时调⽤,并将异步操作的结果,作为参数传递出去; reject 函数的作⽤是,将 Promise 对象的状态从“未完成”变为“失败”(即从 pending 变为 rejected)
let promise = new Promise(excutor)
2. 实例⽅法
Promise.prototype.then() 为 Promise 实例添加状态改变时的回调函数,该函数的第⼀个参数是 resolved 状态的回 调函数,第⼆个参数是 rejected 状态的回调函数,它们都是可选的。
Promise.prototype.catch() 为 Promise 实例指定发⽣错误时的回调函数。是then(null,callback)的别名。
Promise.prototype.finally() 该⽅法⽤于指定不管 Promise 对象最后状态如何,都会执⾏的操作
3.静态方法
iteratiorable表示可迭代的对象 常见数组或set...
Promise.all(iteratorable)
Promise.all([p1,p2])(p1,p2是promise实例)
当p1 p2 ...全部执行完毕并且状态resolved的时候,promise的then才会被调用,该then的回调函数的参数是p1,p2...的运行结果 ,如果报错是哪个先报错就返回哪个,只返回一个
这个新的promise对象在触发成功状态以后,会把⼀个包含iterable⾥所有promise返回值的数组作为成功回调的返回值,顺序跟iterable的顺序保持⼀致;如果这个新的promise对象触发了失败状态,它会把iterable⾥第⼀个触发失败的promise对象的错误信息作为它的失败错误信息
案例: 当查询完所有的班级,渠道后再调用查询学生的接口,查询学生的时候默认查询第一个班级
Promise.all([p1,p2]).then((result)=>{
let defaultClass=result[0].data.data[0]
loadStudent();
})
Promise.race(iteratorable)
返回率先改变状态的promise结果
Promise.allSettled(iteratorable)
返回值为promise 与all不同,当所有的承诺对象状态已经确认的时候,会执行then then的参数为promise对象的结果
Promise.resolve()
直接返回一个承诺对象,状态为成功
Promise.reject()
直接返回一个承诺对象,状态为失败
2. 迭代器
当需要对⼀个对象进⾏迭代时(⽐如开始⽤于⼀个 for..of 循环中),它的 Symbol.iterator ⽅法都会在不传参情况下被调⽤,返回的迭代器⽤于获取要迭代的值。 ⼀些内置类型 拥有默认的迭代器⾏为,如下:
Array.prototype[Symbol.iterator]()
TypedArray.prototype[Symbol.iterator]()
String.prototype[Symbol.iterator]()
Map.prototype[Symbol.iterator]()
Set.prototype[Symbol.iterator]()
ES6可迭代的对象
数组
字符串
set
map
因为:他们的实例对象可以直接访问Symbol.iterator ,构造函数实现了Symbol.iterator接口
Iterator 的遍历过程如下:
1. 创建⼀个指针对象,指向当前数据结构的起始位置。也就是说,遍历器对象本质上,就是⼀ 个指针对象。
2. 第⼀次调⽤指针对象的 next ⽅法,可以将指针指向数据结构的第⼀个成员。
3. 第⼆次调⽤指针对象的 next ⽅法,指针就指向数据结构的第⼆个成员。
4. 不断调⽤指针对象的 next ⽅法,直到它指向数据结构的结束位置。 每⼀次调⽤ next ⽅法,都会返回数据结构的当前成员的信息。具体来说,就是返回⼀个 包含 value 和 done 两个属性的对象。其中, value 属性是当前成员的值, done 属性是 ⼀个布尔值,表示遍历是否结束。
调⽤ Iterator 接⼝的场合
扩展运算符
yield *
for...of
Array.from()
Map(), Set(), WeakMap(), WeakSet()(⽐如new Map([['a',1],['b',2]]))
Promise.all()
Promise.race()
3.generator函数
形式上来看,Generator 函数是⼀个普通函数,但是有两个特征。⼀是, function 关键 字与函数名之间有⼀个星号;⼆是,函数体内部使⽤ yield 表达式,定义不同的内部状态
function* helloWorldGenerator() {
yield 'hello';
yield 'world';
return 'ending';
}
var hw = helloWorldGenerator();
返回值是个迭代器,使得异步操作同步化
1.迭代器函数本质上就是一个generator函数
调⽤ Generator 函数,返回⼀个遍历器对象,代表 Generator 函数的内部指针。以后,每 次调⽤遍历器对象的 next ⽅法,就会返回⼀个有着 value 和 done 两个属性的对象。 value 属性表示当前的内部状态的值,是 yield 表达式后⾯那个表达式的值; done 属性是 ⼀个布尔值,表示是否遍历结束。
2.next参数
next参数可以作为上一个yield表达式的返回值
let iterator = foo()
iterator.next(1)
function* gen(x){
let y = yield x+1;
return y
}
let iterator = gen(5);
iterator.next() // 6
iterator.next(8) //8
3.generator函数实现⾃定义迭代器
创建⼀个类数组对象的类,⽤于⽣成类数组对象,并且实现类数组对象的迭代器函数。
class ArrayLike{
constructor(args){
for(let i=0;i<args.length;i++){
let val = args[i]
this[i] = val;
}
Object.defineProperty(this,'length',{
configurable:true,
enumerable:false,
value:args.length
})
}
// 请你实现迭代函数
* [Symbol.iterator](){
for(let k in this){
let v = this[k]
let index = parseInt(k)
yield {value:v,done:index<this.length?false:true}
}
}
}
let arr = new ArrayLike(['terry','larry','tom']);
console.log(arr);
for(let a of arr){
console.log(a);
}
4. 异步任务封装
axios的get⽅法可以返回⼀个promise对象,通过yield表达式可以阻塞ajax代码的执⾏,如 下代码中,我们需要获取yield表达式的结果,这时候就需要为next⽅法传递参数。
let axios = require('axios');
function* foo(){
let url = 'http://121.199.29.84:8001/index/carousel/findAll'
let resp = yield axios.get(url)
console.log(resp.data);
}
// 这里的执行是比较麻烦的
let iterator = foo();
iterator.next().value.then(resp => {
iterator.next(resp);
});
5. co模块
co模块是著名程序员 TJ Holowaychuk 于 2013 年 6 ⽉发布的⼀个⼩⼯具,⽤于 Generator 函数的⾃动执⾏。该函数返回⼀个 Promise 对象,因此可以⽤ then ⽅法添加回调函数。
let axios = require('axios');
let co = require('co')
function* foo(){
let url = 'http://121.199.29.84:8001/index/carousel/findAll'
let resp = yield axios.get(url)
console.log(resp.data);
}
co(foo)
4. Async函数
异步函数
async 函数就是 Generator 函数的语法糖。使得异步操作变得更加⽅便。 async 函数就 是将 Generator 函数的星号( * )替换成 async ,将 yield 替换成 await ,仅此⽽已。 异步函数的运⾏结果为Promise对象,异步函数内部的返回值会作为 then ⽅法回调函数 的参数。
let axios = require('axios');
async function foo(){
let url = 'http://121.199.29.84:8001/index/carousel/findAll'
let resp = await axios.get(url)
console.log(resp.data);
}
foo();
await 命令后⾯是⼀个 Promise 对象,返回该对象的结果。如果不是 Promise 对象,就 直接返回对应的值。