观看之前请先认识promise的基本利用
一、分析promise由哪些东西构成
在一样平常的利用中,我们可以知道,一个完备的promise应当包罗乐成、失败、举行中这三个状态,同时尚有resolve,reject两个改变状态的成员函数。末了还会有一个then函数来吸收promise的实验结果
在相识了上述的内容之后,一个promise的雏形就出来了
class myPromise { constructor(executor) { //默认状态为pending this.status = 'pending' //乐成的默认值为undefined this.successVal = undefined //失败的默认值为undefined this.errorVal = undefined //初始化时调用传入的回调函数 executor(this.resolve,this.reject) } resolve = (data) => { } reject = (err) => { } then = (success_cb,error_cb) => { }}这里要分析一下,then函数,大概在一样平常利用中各人都风俗性的只传入一个参数。实在then是有两个参数的,第一个参数是promise乐成时调用,第二个参数是失败时调用。而我们熟知的catch函数,实在内部就是调用的then函数,只不外传入的是失败的回调
catch = (err_cb) => { this.then(undefined, err_cb) }下面来完善一下几个函数的内容
resolve = (data) => { if (this.status === 'pending') { this.status = 'success' this.successVal = data } } reject = (err) => { if (this.status === 'pending') { this.status = 'error' this.errorVal = err } } then = (success_cb,error_cb) => { setTimeout(() => { if (this.status === 'success') { success_cb(this.successVal ) }else if(this.status === 'error'){ success_cb(this.errorVal ) } }) }如许,一个浅显版的promise就实现了。
接下来就必要去实现promise处置惩罚异步标题。
起首分析一下,出现了异步代码之后会发生什么环境:
通常利用一个有异步的promise会如许
new Promise((resolve,reject)=>{ setTimeout(()=>{ resolve(123) },2000)})如许我们在调用then的时间实在resolve还没有被实验,promise的状态也并没有变动。以是我们要做的就是讲then函数吸收到的参数存起来,比及promise的状态变了之后再去调用他。如许就能做到处置惩罚异步标题了
constructor(executor) { //默认状态为pending this.status = 'pending' //乐成的默认值为undefined this.successVal = undefined //失败的默认值为undefined this.errorVal = undefined //存放乐成的回调函数 this.successCallBackList = [] //存放失败的回调函数 this.errorCallBackList = [] //自动实验一次传入的回调函数 try { executor(this.resolve, this.reject) } catch (err) { this.reject(err) } } resolve = (data) => { if (this.status === 'pending') { this.status = 'success' this.successVal = data this.successCallBackList.forEach(fn => fn(this.successVal)) } } reject = (err) => { if (this.status === 'pending') { this.status = 'error' this.errorVal = err this.errorCallBackList.forEach(fn => fn(this.errorVal)) } } then = (success_cb,error_cb) => { setTimeout(() => { if (this.status === 'success') { success_cb(this.successVal ) }else if(this.status === 'error'){ success_cb(this.errorVal ) }else{ this.successCallBackList.push(success_cb) this.errorCallBackList.push(error_cb) } }) }上面代码中就是在then里判定当前状态,假如为pending的话就将回调存入对应的数组,然后再resolve和reject函数中去遍历存放回调的数组而且逐一实验里头的函数。
如许异步标题也处置惩罚好了。
接下来就是最告急的处置惩罚then的链式回调了。这也是promise的特色。
起首必要明白的一点是,promise的then函数会返回一个新的promise,如许我们才可以做到不停.then调用。其次,反面的then会拿到上一个then的返回值。
明白了这个概念之后我们就可以去动手写then函数了
then = (success_cb, error_cb) => { const promise2 = new myPromise((resolve, reject) => { if (this.status === 'success') { setTimeout(() => { try { if (typeof success_cb !== 'function') { resolve(this.successVal) } else { let x = success_cb(this.successVal) resolvePromise(promise2, x, resolve, reject) } } catch (err) { reject(err) } }) } else if (this.status === 'error') { setTimeout(() => { try { if (typeof error_cb !== 'function') { reject(this.errorVal) } else { let x = error_cb(this.errorVal) resolvePromise(promise2, x, resolve, reject) } } catch (err) { reject(err) } }) } else { this.successCallBackList.push(() => { setTimeout(() => { try { if (typeof success_cb !== 'function') { resolve(this.successVal) } else { let x = success_cb(this.successVal) resolvePromise(promise2, x, resolve, reject) } } catch (err) { reject(err) } }) }) this.errorCallBackList.push(() => { setTimeout(() => { try { if (typeof error_cb !== 'function') { reject(this.errorVal) } else { let x = error_cb(this.errorVal) resolvePromise(promise2, x, resolve, reject) } } catch (err) { reject(err) } }) }) } } ) return promise2 } /** * @param promise2 promise1.then中返回的新的promise * @param x promise1中then方法的回调函数返回的值 * @param resolve promise2的reslove回调 * @param reject promise2的reject回调 */ function resolvePromise(promise2, x, resolve, reject) { if (x === promise2) { /** * 假如x等于promis2 则抛出非常,防止陷入死循环 抛出的非常会被上一个promise的then方法捕获到而且直接走reject方法 */ throw new TypeError('Chaining cycle detected for promise'); } if (x instanceof myPromise) { /** * 假如 x 为 Promise ,则使 promise2 担当 x 的状态 * 也就是继承实验x,假如实验的时间拿到一个y,还要继承剖析y */ x.then(y => { resolvePromise(promise2, y, resolve, reject) }, reject) } else if (x !== null && ((typeof x === 'object') || (typeof x === 'function'))) { try { var then = x.then } catch (e) { return reject(e) } if (typeof then === 'function') { let called = false //防止多次调用 try { then.call(x, y => { if (called) return called = true resolvePromise(promise2, y, resolve, reject) }, err => { if (called) return called = true reject(err) }) } catch (err) { if (called) return called = true reject(err) } } else { resolve(x) } } else { resolve(x) } }resolvePromise函数就是处置惩罚上一个then函数的返回值的工具函数。
then函数里的逻辑大抵上就是,返回一个新的promise,这个新的promise里可以访问到上一个promise的全部属性,同时可以通过调用自身的resolve和reject改变自身的状态,并将上一个promise的then函数的返回值作为参数保存下来,如许他本身的then函数就可以访问到这个值了。也就是我们所说的下一个then能拿到上一个then的返回值。而在then函数中大概返回各种环境的值,以是写了一个resolvePromise函数来处置惩罚各种环境。
以上就是一个完备的promise了。告急的就是明白then函数的链式回调。把这个搞明白了,整个promise也就豁然开朗了。
别的附上完备的代码
/** * @param promise2 promise1.then中返回的新的promise * @param x promise1中then方法的回调函数返回的值 * @param resolve promise2的reslove回调 * @param reject promise2的reject回调 */ function resolvePromise(promise2, x, resolve, reject) { if (x === promise2) { /** * 假如x等于promis2 则抛出非常,防止陷入死循环 抛出的非常会被上一个promise的then方法捕获到而且直接走reject方法 */ throw new TypeError('Chaining cycle detected for promise'); } if (x instanceof myPromise) { /** * 假如 x 为 Promise ,则使 promise2 担当 x 的状态 * 也就是继承实验x,假如实验的时间拿到一个y,还要继承剖析y */ x.then(y => { resolvePromise(promise2, y, resolve, reject) }, reject) } else if (x !== null && ((typeof x === 'object') || (typeof x === 'function'))) { try { var then = x.then } catch (e) { return reject(e) } if (typeof then === 'function') { let called = false //防止多次调用 try { then.call(x, y => { if (called) return called = true resolvePromise(promise2, y, resolve, reject) }, err => { if (called) return called = true reject(err) }) } catch (err) { if (called) return called = true reject(err) } } else { resolve(x) } } else { resolve(x) } } class myPromise { //静态resolve方法,可以让利用者直接通过类来访问,不必要实例化这个类。同时以static关键字标识的属性不会被实例继承,只能通过类自身访问 static resolve() { } constructor(executor) { //默认状态为pending this.status = 'pending' //乐成的默认值为undefined this.successVal = undefined //失败的默认值为undefined this.errorVal = undefined //存放乐成的回调函数 this.successCallBackList = [] //存放失败的回调函数 this.errorCallBackList = [] //自动实验一次传入的回调函数 try { executor(this.resolve, this.reject) } catch (err) { this.reject(err) } } resolve = (data) => { if (this.status === 'pending') { this.status = 'success' this.successVal = data this.successCallBackList.forEach(fn => fn(this.successVal)) } } reject = (err) => { if (this.status === 'pending') { this.status = 'error' this.errorVal = err this.errorCallBackList.forEach(fn => fn(this.errorVal)) } } then = (success_cb, error_cb) => { const promise2 = new myPromise((resolve, reject) => { if (this.status === 'success') { setTimeout(() => { try { if (typeof success_cb !== 'function') { resolve(this.successVal) } else { let x = success_cb(this.successVal) //浅显处置惩罚then if(x instanceof myPromise){ if(x.status==='pending'){ x.then() }else{ //x的状态不处于pending状态,则将新的promise的resolve和reject作为x的then函数的参数传入 //如许,当x的状态变动了,就会调用我们传入的resolve和reject。而且会将x的终极值传入。 x.then(resolve, reject) } }else{ resolve(x) } // resolvePromise(promise2, x, resolve, reject) } } catch (err) { reject(err) } }) } else if (this.status === 'error') { setTimeout(() => { try { if (typeof error_cb !== 'function') { reject(this.errorVal) } else { let x = error_cb(this.errorVal) resolvePromise(promise2, x, resolve, reject) } } catch (err) { reject(err) } }) } else { this.successCallBackList.push(() => { setTimeout(() => { try { if (typeof success_cb !== 'function') { resolve(this.successVal) } else { let x = success_cb(this.successVal) resolvePromise(promise2, x, resolve, reject) } } catch (err) { reject(err) } }) }) this.errorCallBackList.push(() => { setTimeout(() => { try { if (typeof error_cb !== 'function') { reject(this.errorVal) } else { let x = error_cb(this.errorVal) resolvePromise(promise2, x, resolve, reject) } } catch (err) { reject(err) } }) }) } } ) return promise2 } catch = (err_cb) => { this.then(undefined, err_cb) } } |