PromiseA+规范
术语
1、Promise是定义一个有then方法的对象和函数
2、thenable是一个可以有then方法的对象或函数
3、value 是Promise成功时的值,resolve(value) value 可以是 thenable,promise,undefined等基本类型或引用类型
4、reason是Promise失败时的值,reject(reason)
5、exception是throw异常时抛出的
规范
Promise状态及他们之间的流转关系
1、pending初始状态,可以被改变
1、在resolve和reject之前都是这个状态
2、通过resolve->fulfilled状态
3、通过reject->rejected的状态
2、fulfilled最终态
1、是promise被resolve后是这个状态
2、它必须有一个value值
3、rejected最终态
1、一个Promise被reject后是这个状态
2、它必须有一个reason值
then应该是promise对外提供的一个方法,用来访问最终结果
Promise.then(onFulfilled, onRejected)
onFulfilled必须是函数,如果不是函数,应该被忽略。
onRejected必须是函数,如果不是函数,应该被忽略。
onFulfilled特性
1、在Promise变成fulfilled时,应该调用onFulfilled,参数是value
2、在promise变成fulfilled之前,不应该被调用
3、只能被调用一次
onRejected特性
1、在Promise变成rejected时,应该调用OnRejected,参数是reason
2、在Promise变成rejected之前,不应该被调用
3、只能被调用一次
OnFulfilled和OnRejected执行时应该是在微任务里面
微任务:是宏任务完成之后再去执行(实现时如何生成微任务)
then方法可以被执行多次
1、promise状态变成fulfilled之后,所有的回调都会按照注册的顺序执行,按照.then顺序执行
2、promise状态变成rejected之后,所有的回调都会按照注册的顺序执行,按照.then顺序执行
返回值
then的返回值应该是一个Promise
const promise2 = Promise.then(onFulfilled, onRejectd);
1、onFulfilled或OnRejected,执行结果为X,调用resolvePromise
2、onFulfilled或OnRejected,如果不返回结果,抛出异常,返回值也需要被reject。
3、如果onFulfiled不是一个函数,Promise2以Promise1的value触发fulfilled
4、如果onFulfiled不是一个函数,Promise2以Promise1的reason触发rejected
resolvePromise
resolvePromise(promise2, x, resolve, reject)
1、如果promise2和x相等,那么 reject TypeError
2、如果x是一个promise
如果x是pending状态,那么promise必须要在pending,直到x变成fulfilled or rejected.
如果x被fulfilled,fulfill promise with the same value.
如果x被rejected,reject promise with the same reason.
3、如果x是一个object或者是一个function
let then = x.then如果x.then这步出错,那么reject promise with the same reason.
如果then是一个函数,then.call(x, resolvePromiseFn, rejectPromise)
resolvePromiseFn的入参是y,执行resolvePromise(promise2, y, resolve, reject);
rejectPromise的入参是r, reject promise with r.
如果resolve Promise和rejectPromise都调用了,那么第一个调用优先,后面的调用忽略。
如果调用then抛出异常e
如果resolvePromise 或 rejectPromise 已经被调用,那么忽略则reject promise wiht the same reason..
如果then不是一个function。fulfill promise with x.
按照规范实现Promise
const PENDING = 'pending';
const FULFILLED = 'fulfilled';
const REJECTED = 'rejected';
class MPromise{
FULFILLED_CALLBACK_LIST = [];
REJECTED_CALLBACK_LIST = [];
_status = PENDING;
constructor(fn){
this.status = PENDING;
this.value = null;
this.reason = null;
try{
fn(this.resolve.bind(this), this.reject.bind(this));
}catch(e){
this.reject(e)
}
}
get status(){
return this._status;
}
set status(newStatus){
this._status = newStatus;
switch(newStatus){
case FULFILLED: {
this.FULFILLED_CALLBACK_LIST.forEach(callback =>{
callback(this.value);
});
break;
}
case REJECTED: {
this.REJECTED_CALLBACK_LIST.forEach(callback=>{
callback(this.reason);
})
break;
}
}
}
resolve(value){
if(this.status === PENDING){
this.status = FULFILLED;
this.value = value;
}
}
reject(reason){
if(this.status === PENDING){
this.status = REJECTED;
this.reason = reason;
}
}
then(onFulfilled, onRejected){
var self = this;
const fulfilledFn = this.isFunction(onFulfilled) ? onFulfilled : (value)=>{
return value;
}
const rejectedFn = this.isFunction(onRejected) ? onRejected : (reason) =>{
throw reason;
}
var thenPromise = new MPromise((resolve, reject)=>{
const fulFiledMicroQueueTask = cb =>{
queueMicrotask(()=>{
try {
const x = fulfilledFn(this.value)
self.resolvePromise(thenPromise, x, resolve, reject);
} catch (error) {
reject(error);
throw new Error(error);
}
})
}
const rejectedMicroQueueTask = cb =>{
queueMicrotask(()=>{
try {
const x = rejectedFn(this.value)
self.resolvePromise(thenPromise, x, resolve, reject);
} catch (error) {
reject(error);
throw new Error(error);
}
})
}
switch(this.status){
case FULFILLED: {
fulFiledMicroQueueTask();
}
case REJECTED: {
rejectedMicroQueueTask();
}
case PENDING: {
self.FULFILLED_CALLBACK_LIST.push(fulFiledMicroQueueTask);
self.REJECTED_CALLBACK_LIST.push(rejectedMicroQueueTask);
}
}
})
return thenPromise;
}
resolvePromise(thenPromise, x, resolve, reject){
if(x === thenPromise){
throw new Error('不能返回自身')
}
if(x instanceof MPromise){
queueMicroTask(()=>{
x.then((y)=>{
this.resolvePromise(thenPromise, y, resolve, reject);
}, reject);
})
} else if(typeof x === 'object' || this.isFunction(x) ) {
if(x === null){
return resolve(x);
}
let then = null;
try{
then = x.then;
}catch(e){
reject(e);
}
if(this.isFunction(then)){
let called = false;
try{
then.call(x,
(y)=>{
if(called){
return ;
}
called = true;
this.resolvePromise(thenPromise, y,resolve, reject);
},
r=>{
if(called){
return ;
}
called = true;
reject(r);
}
}catch(e){
if(called){
return ;
}
called = true;
reject(e);
}
}
} else {
resolve(x);
}
}
isFunction(param){
return typeof param === 'function';
}
catch(onRejected){
return this.then(null, onRejected);
}
static resolve(value){
if(value instanceof MPromise){
return value;
}
return new MPromise((resolve)=>{
resolve(value);
})
}
static reject(reason){
return new MPromise((resolve, reject) =>{
reject(reason);
})
}
static all(promiseList){
return new MPromise((resolve, reject) => {
const length = promiseList.length;
for(let i = 0; i< length; i++){
promiseList[i].then(function(data){
arr[index] = data;
if(i==length-1){
resolve(arr);
}
}, reject)
}
})
}
static race(promiseList){
return new MPromise((resolve, reject) => {
for(var i = 0; i< promiseList.length; i++){
promiseList[i].then(resolve, reject)
}
})
}
}
const test = new MPromise((resolve, reject) =>{
setTimeout(()=>{
resolve(111);
}, 1000);
}).then(console.log);
console.log(test)
setTimeout(()=>{
console.log(test);
}, 2000)
genterator
迭代器 Iterator
迭代器Iterator 是 ES6 引入的一种新的遍历机制,同时也是一种特殊对象,它具有一些专门为迭代过程设计的专有接口。
每个迭代器对象都有一个next()方法,每次调用都返回一个当前结果对象。当前结果对象中有两个属性:
-
value:当前属性的值
-
done:用于判断是否遍历结束,当没有更多可返回的数据时,返回true
每调用一次next()方法,都会返回下一个可用的值,直到遍历结束。
生成器 Generator
生成器是一种返回迭代器的函数,通过function关键字后的星号(*)来表示,函数中会用到新的关键字yield。星号可以紧挨着function关键字,也可以在中间添加一个空格.
// yield 暂停标志
// next方法可以恢复执行。
function* helloWorldGenerator() {
yield 'hello';
yield 'world';
return 'ending';
}
var hw = helloWorldGenerator();
hw.next();
//{value: 'hello', done: false}
hw.next();
//{value: 'world', done: false}
hw.next();
//{value: 'ending', done: true}
hw.next();
//{value: undefined, done: true}
async,await
async函数就是将 Generator 函数的星号(*)替换成async,将yield替换成await,仅此而已。
根据语法规格,await命令只能出现在 async 函数内部,否则都会报错。
async function fn(args){}
// 等同于
function fn(args){
return spawn(function* (){
});
}
function spawn(genF) {
return new Promise(function(resolve, reject) {
const gen = genF();
function step(nextF) {
let next;
try {
next = nextF();
} catch(e) {
return reject(e);
}
if(next.done) {
return resolve(next.value);
}
Promise.resolve(next.value).then(function(v) {
step(function() { return gen.next(v); });
}, function(e) {
step(function() { return gen.throw(e); });
});
}
step(function() { return gen.next(undefined); });
});
}