promise声明
首先呢,promise肯定是一个类,我们就用class来声明。
• 由于 new Promise((resolve, reject)=>{}) ,所以传入一个参数(函数),executor,传入就执行。
•executor里面有两个参数,一个叫resolve(成功),一个叫reject(失败)。
•由于resolve和reject可执行,所以都是函数
•Promise存在三个状态(state)pending、fulfilled、rejected
•pending(等待态)为初始态,并可以转化为fulfilled(成功态)和rejected(失败态)
•成功时,不可转为其他状态,且必须有一个不可改变的值(value)
•失败时,不可转为其他状态,且必须有一个不可改变的原因(reason)
• new Promise((resolve, reject)=>{resolve(value)}) resolve为成功,接收参数value,状态改变为fulfilled,不可再次改变。
• new Promise((resolve, reject)=>{reject(reason)}) reject为失败,接收参数reason,状态改变为rejected,不可再次改变。
•若是executor函数报错 直接执行reject();
const PENDING = 'pending'; // 等待const FULFILLED = 'fulfilled'; // 成功const REJECTED = 'rejected'; // 失败class MyPromise {// 生成器constructor(executor) {// executor 立即执行// 成功执行 resolve或rejecttry {executor(this.resolve, this.reject);} catch (e) {//失败执行rejectthis.reject(e);}}status = PENDING;value = undefined;reason = undefined;resolve = (value) => {// 如果状态不是等待 阻止程序向下执行if (this.status !== PENDING) return;// 将状态更改为成功this.status = FULFILLED;// 保存成功之后的值this.value = value;};reject = (reason) => {// 如果状态不是等待 阻止程序向下执行if (this.status !== PENDING) return;// 将状态更改为失败this.status = REJECTED;// 保存失败后的原因this.reason = reason;}
then 方法
Promise有一个叫做then的方法,里面有两个参数:onFulfilled,onRejected,成功有成功的值,失败有失败的原因
•当状态state为fulfilled,则执行onFulfilled,传入this.value。当状态state为rejected,则执行onRejected,传入this.value
•onFulfilled,onRejected如果他们是函数,则必须分别在fulfilled,rejected后被调用,value或reason依次作为他们的第一个参数
then(successCallback, failCallback) {// 同步情况下成功时执行成功回调if (this.status === FULFILLED) {successCallback(this.value);// 同步情况下失败时执行失败回调} else if (this.status === REJECTED) {failCallback(this.reason);}}
解决异步实现
现在基本可以实现简单的同步代码,但是当resolve在setTomeout内执行,then时state还是pending等待状态 我们就需要在then调用的时候,将成功和失败存到各自的数组,一旦reject或者resolve,就调用它们
类似于发布订阅,先将then里面的两个函数储存起来,由于一个promise可以有多个then,所以存在同一个数组内。
const PENDING = 'pending'; // 等待const FULFILLED = 'fulfilled'; // 成功const REJECTED = 'rejected'; // 失败class MyPromise {// 生成器constructor(executor) {// executor 立即执行// 成功执行 resolve或rejecttry {executor(this.resolve, this.reject);} catch (e) {//失败执行rejectthis.reject(e);}}status = PENDING;value = undefined;reason = undefined;// 成功回调successCallback = [];// 失败回调failCallback = [];resolve = (value) => {// 如果状态不是等待 阻止程序向下执行if (this.status !== PENDING) return;// 将状态更改为成功this.status = FULFILLED;// 保存成功之后的值this.value = value;// 判断成功回调是否存在 如果存在 调用while (this.successCallback.length) {this.successCallback.shift()();}};reject = (reason) => {// 如果状态不是等待 阻止程序向下执行if (this.status !== PENDING) return;// 将状态更改为失败this.status = REJECTED;// 保存失败后的原因this.reason = reason;// 判断成功回调是否存在 如果存在 调用while (this.failCallback.length) {this.failCallback.shift()();}};then(successCallback, failCallback) {if (this.status === FULFILLED) {// 回调的函数是否异步successCallback(this.value);// 同步情况下失败时执行失败回调} else if (this.status === REJECTED) {failCallback(this.reason);//异步情况下执行} else {// onFulfilled传入到成功数组this.successCallback.push(() => {successCallback(this.value);});// onRejected传入到失败数组this.failCallback.push(() => {failCallback(this.reason);});}});}
解决链式调用
我门常常用到 new Promise().then().then() ,这就是链式调用,用来解决回调地狱
1、为了达成链式,我们默认在第一个then里返回一个promise。秘籍规定了一种方法,就是在then里面返回一个新的promise,称为promise2: promise2 = new Promise((resolve, reject)=>{})
•将这个promise2返回的值传递到下一个then中
•如果返回一个普通的值,则将普通的值传递给下一个then中
2、当我们在第一个then中 return 了一个参数(参数未知,需判断)。这个return出来的新的promise就是onFulfilled()或onRejected()的值
秘籍则规定onFulfilled()或onRejected()的值,即第一个then返回的值,叫做x,判断x的函数叫做resolvePromise
const PENDING = 'pending'; // 等待const FULFILLED = 'fulfilled'; // 成功const REJECTED = 'rejected'; // 失败class MyPromise {// 生成器constructor(executor) {// executor 立即执行// 成功执行 resolve或rejecttry {executor(this.resolve, this.reject);} catch (e) {//失败执行rejectthis.reject(e);}}status = PENDING;value = undefined;reason = undefined;// 成功回调successCallback = [];// 失败回调failCallback = [];resolve = (value) => {// 如果状态不是等待 阻止程序向下执行if (this.status !== PENDING) return;// 将状态更改为成功this.status = FULFILLED;// 保存成功之后的值this.value = value;// 判断成功回调是否存在 如果存在 调用while (this.successCallback.length) {this.successCallback.shift()();}};reject = (reason) => {// 如果状态不是等待 阻止程序向下执行if (this.status !== PENDING) return;// 将状态更改为失败this.status = REJECTED;// 保存失败后的原因this.reason = reason;// 判断成功回调是否存在 如果存在 调用while (this.failCallback.length) {this.failCallback.shift()();}};then(successCallback, failCallback) {let promise2 = new MyPromise((resolve, reject) => {// 同步情况下成功时执行成功回调if (this.status === FULFILLED) {// 回调的函数是否异步try {let x = successCallback(this.value);resolvePromise(promise2, x, resolve, reject);} catch (e) {reject(e);}// 同步情况下失败时执行失败回调} else if (this.status === REJECTED) {try {let x = failCallback(this.reason);resolvePromise(promise2, x, resolve, reject);} catch (e) {reject(e);}//异步情况下执行} else {// onFulfilled传入到成功数组this.successCallback.push(() => {try {let x = successCallback(this.value);resolvePromise(promise2, x, resolve, reject);} catch (e) {reject(e);}});// onRejected传入到失败数组this.failCallback.push(() => {try {let x = successCallback(this.value);resolvePromise(promise2, x, resolve, reject);} catch (e) {reject(e);}});}});return promise2;}}
完成resolvePromise函数
秘籍规定了一段代码,让不同的promise代码互相套用,叫做resolvePromise
•如果 x === promise2,则是会造成循环引用,自己等待自己完成,则报“循环引用”错误
let p = new Promise(resolve => {resolve(0);});var p2 = p.then(data => {// 循环引用,自己等待自己完成,一辈子完不成return p2;})
1、判断x
• Otherwise, if x is an object or function,Let then be x.then
•x 不能是null
•x 是普通值 直接resolve(x)
• x 是对象或者函数(包括promise), let then = x.then 2、当x是对象或者函数(默认promise)
•声明了then
•如果取then报错,则走reject()
•如果then是个函数,则用call执行then,第一个参数是this,后面是成功的回调和失败的回调
•如果成功的回调还是pormise,就递归继续解析 3、成功和失败只能调用一个 所以设定一个called来防止多次调用
function resolvePromise(promsie2, x, resolve, reject) {if (promsie2 === x) {return reject(new TypeError('Chaining cycle detected for promis'));}if (x instanceof MyPromise) {// promise 对象x.then((value) => resolve(value),(reason) => reject(reason));} else {// 普通值resolve(x);}}
解决其他问题
1、秘籍规定onFulfilled,onRejected都是可选参数,如果他们不是函数,必须被忽略
• onFulfilled返回一个普通的值,成功时直接等于 value => value
• onRejected返回一个普通的值,失败时如果直接等于 value => value,则会跑到下一个then中的onFulfilled中,所以直接扔出一个错误 reason => throw err 2、秘籍规定onFulfilled或onRejected不能同步被调用,必须异步调用。我们就用setTimeout解决异步问题
•如果onFulfilled或onRejected报错,则直接返回reject()
const PENDING = 'pending'; // 等待const FULFILLED = 'fulfilled'; // 成功const REJECTED = 'rejected'; // 失败class MyPromise {// 生成器constructor(executor) {// executor 立即执行// 成功执行 resolve或rejecttry {executor(this.resolve, this.reject);} catch (e) {//失败执行rejectthis.reject(e);}}status = PENDING;value = undefined;reason = undefined;// 成功回调successCallback = [];// 失败回调failCallback = [];resolve = (value) => {// 如果状态不是等待 阻止程序向下执行if (this.status !== PENDING) return;// 将状态更改为成功this.status = FULFILLED;// 保存成功之后的值this.value = value;// 判断成功回调是否存在 如果存在 调用while (this.successCallback.length) {this.successCallback.shift()();}};reject = (reason) => {// 如果状态不是等待 阻止程序向下执行if (this.status !== PENDING) return;// 将状态更改为失败this.status = REJECTED;// 保存失败后的原因this.reason = reason;// 判断成功回调是否存在 如果存在 调用while (this.failCallback.length) {this.failCallback.shift()();}};then(successCallback, failCallback) {// successCallback如果不是函数,就忽略successCallback,直接返回valuesuccessCallback = successCallback ? successCallback : (value) => value;// failCallback如果不是函数,就忽略failCallback,直接扔出错误failCallback = failCallback? failCallback: (reason) => {throw reason;};let promise2 = new MyPromise((resolve, reject) => {// 同步情况下成功时执行成功回调if (this.status === FULFILLED) {// 回调的函数是否异步setTimeout(() => {try {let x = successCallback(this.value);resolvePromise(promise2, x, resolve, reject);} catch (e) {reject(e);}}, 0);// 同步情况下失败时执行失败回调} else if (this.status === REJECTED) {setTimeout(() => {try {let x = failCallback(this.reason);resolvePromise(promise2, x, resolve, reject);} catch (e) {reject(e);}}, 0);//异步情况下执行} else {// onFulfilled传入到成功数组this.successCallback.push(() => {setTimeout(() => {try {let x = successCallback(this.value);resolvePromise(promise2, x, resolve, reject);} catch (e) {reject(e);}}, 0);});// onRejected传入到失败数组this.failCallback.push(() => {setTimeout(() => {try {let x = successCallback(this.value);resolvePromise(promise2, x, resolve, reject);} catch (e) {reject(e);}}, 0);});}});return promise2;}}function resolvePromise(promsie2, x, resolve, reject) {if (promsie2 === x) {return reject(new TypeError('Chaining cycle detected for promis'));}if (x instanceof MyPromise) {// promise 对象x.then((value) => resolve(value),(reason) => reject(reason));} else {// 普通值resolve(x);}}
catch
catch(fn){return this.then(null,fn);}
resolve
//resolve方法static resolve = (val) => {return new Promise((resolve, reject) => {resolve(val);});};
reject
//reject方法static reject = (val) => {return new Promise((resolve, reject) => {reject(val);});};
race
//race方法static race = (promises) => {return new Promise((resolve, reject) => {for (let i = 0; i < promises.length; i++) {promises[i].then(resolve, reject);}});};
all
static all = (promises)=>{let arr = [];let i = 0;function processData(index,data){arr[index] = data;i++;if(i == promises.length){resolve(arr);};};return new Promise((resolve,reject)=>{for(let i=0;i<promises.length;i++){promises[i].then(data=>{processData(i,data);},reject);};});}
完整代码
const PENDING = 'pending'; // 等待const FULFILLED = 'fulfilled'; // 成功const REJECTED = 'rejected'; // 失败class MyPromise {// 生成器constructor(executor) {// executor 立即执行// 成功执行 resolve或rejecttry {executor(this.resolve, this.reject);} catch (e) {//失败执行rejectthis.reject(e);}}status = PENDING;value = undefined;reason = undefined;// 成功回调successCallback = [];// 失败回调failCallback = [];resolve = (value) => {// 如果状态不是等待 阻止程序向下执行if (this.status !== PENDING) return;// 将状态更改为成功this.status = FULFILLED;// 保存成功之后的值this.value = value;// 判断成功回调是否存在 如果存在 调用while (this.successCallback.length) {this.successCallback.shift()();}};reject = (reason) => {// 如果状态不是等待 阻止程序向下执行if (this.status !== PENDING) return;// 将状态更改为失败this.status = REJECTED;// 保存失败后的原因this.reason = reason;// 判断成功回调是否存在 如果存在 调用while (this.failCallback.length) {this.failCallback.shift()();}};then(successCallback, failCallback) {// successCallback如果不是函数,就忽略successCallback,直接返回valuesuccessCallback = successCallback ? successCallback : (value) => value;// failCallback如果不是函数,就忽略failCallback,直接扔出错误failCallback = failCallback? failCallback: (reason) => {throw reason;};let promise2 = new MyPromise((resolve, reject) => {// 同步情况下成功时执行成功回调if (this.status === FULFILLED) {// 回调的函数是否异步setTimeout(() => {try {let x = successCallback(this.value);resolvePromise(promise2, x, resolve, reject);} catch (e) {reject(e);}}, 0);// 同步情况下失败时执行失败回调} else if (this.status === REJECTED) {setTimeout(() => {try {let x = failCallback(this.reason);resolvePromise(promise2, x, resolve, reject);} catch (e) {reject(e);}}, 0);//异步情况下执行} else {// onFulfilled传入到成功数组this.successCallback.push(() => {setTimeout(() => {try {let x = successCallback(this.value);resolvePromise(promise2, x, resolve, reject);} catch (e) {reject(e);}}, 0);});// onRejected传入到失败数组this.failCallback.push(() => {setTimeout(() => {try {let x = successCallback(this.value);resolvePromise(promise2, x, resolve, reject);} catch (e) {reject(e);}}, 0);});}});return promise2;}catch(fn) {return this.then(null, fn);}//resolve方法static resolve = (val) => {return new Promise((resolve, reject) => {resolve(val);});};//reject方法static reject = (val) => {return new Promise((resolve, reject) => {reject(val);});};//race方法static race = (promises) => {return new Promise((resolve, reject) => {for (let i = 0; i < promises.length; i++) {promises[i].then(resolve, reject);}});};static all = (promises)=>{let arr = [];let i = 0;function processData(index,data){arr[index] = data;i++;if(i == promises.length){resolve(arr);};};return new Promise((resolve,reject)=>{for(let i=0;i<promises.length;i++){promises[i].then(data=>{processData(i,data);},reject);};});}}function resolvePromise(promsie2, x, resolve, reject) {if (promsie2 === x) {return reject(new TypeError('Chaining cycle detected for promis'));}if (x instanceof MyPromise) {// promise 对象x.then((value) => resolve(value),(reason) => reject(reason));} else {// 普通值resolve(x);}}
