「这是我参与11月更文挑战的第20天,活动详情查看:2021最后一次更文挑战」。
传送门
从零手撕Promise,掌握Promise的实现原理(1)之promise基本结构的实现
从零手撕Promise,掌握Promise的实现原理(2)之基础版本的promise实现
从零手撕Promise,掌握Promise的实现原理(3)之回调地狱是什么
从零手撕Promise,掌握Promise的实现原理(4)之then方法链式调用的初步实现
从零手撕Promise,掌握Promise的实现原理(5)之then方法链式调用的进阶实现
从零手撕Promise,掌握Promise的实现原理(6)之then方法的回调为什么是异步微任务
从零手撕Promise,掌握Promise的实现原理(7)then方法链式调用之核心方法resolvePromise
从零手撕Promise,掌握Promise的实现原理(8)then方法链式调用之核心方法resolvePromise再探究
从零手撕Promise,掌握Promise的实现原理(9)then方法链式调用之核心方法resolvePromise完全体
从零手撕Promise,掌握Promise的实现原理(10)then方法完全体
从零手撕Promise,掌握Promise的实现原理(11)之测试完全体Promise是否符合PromiseA+
什么?Promise.resolve()还可以返回失败的Promise(12)
从零手撕Promise,掌握Promise的实现原理(13)之手撕Promise的finally方法
从零手撕Promise,掌握Promise的实现原理(14)之手撕Promise的all方法
回顾
经过上次的文章介绍,我们的Promise完成了all
方法,现在的Promsie已经长这样了。
const PENDING = 'pending'
const FULFILLED = 'fulfilled'
const REJECTED = 'rejected'
const resolvePromise = (promise, x, resolve, reject) => {
//*******************************************************判断x与promsie是否是同一个promise,防止进入死循环*********************//////*********
if(x === promise) throw new TypeError('Chaining cycle detected for promise #<Promise>')
// 1.首先判断`x`是基础类型数据,还是引用类型,基础类型的数据直接`resolve`,即可。
if(x !== null && /^(object|function)$/.test(typeof x)){
let then
// 2. 如果是引用类型的数据,尝试获取`x`上的`then`属性(`x.then`),如果在获取属性的时候报异常则`reject`
try{
then = x.then
}catch(e){
reject(e)
}
//3. 判断`then`是否是函数,如果是一个函数则我们认定它为`Promise`,如果不是则`resolve`
if(typeof then === 'function'){
let called = false //**************************************这里加了变量*************************//////
try{
then.call(x, (y) => {
if(called) return //**************************************这里加了变量*************************//////
called = true
resolvePromise(promise, y, resolve, reject)
},(r) => {
if(called) return//**************************************这里加了变量*************************//////
reject(r)
})
}catch(e){
if(called) return//**************************************这里加了变量*************************//////
reject(e)
}
}else{
resolve(x)
}
}else{
//基础类型数据直接resolve
resolve(x)
}
}
class Promise{
constructor(executor){
this.state = PENDING
this.value = undefined
this.reason = undefined
//存放onFulfilled
this.onResolvedCallbacks = []
//存放onRejected
this.onRejectedCallbacks = []
const resolve = (value) => {
//如果发现value是一个Promise,我们需要调用value的then方法去递归解析
if(value instanceof Promise){
return value.then(resolve,reject); // 递归解析
}
if (this.state === PENDING) {
this.value = value
this.state = FULFILLED
//promise实例状态改变后调用暂存的onFulfilled
this.onResolvedCallbacks.forEach(fn => fn())
}
}
const reject = (reason) => {
if (this.state === PENDING) {
this.reason = reason
this.state = REJECTED
//promise实例状态改变后调用的onRejected
this.onRejectedCallbacks.forEach(fn => fn())
}
}
try {
//executor函数执行过程中出错,将会导致Promise失败
executor(resolve,reject)
} catch (error) {
reject(error)
}
}
then(onFulfilled, onRejected){
onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : v => v
onRejected = typeof onRejected === 'function' ? onRejected : err => { throw err }
let promise = new Promise((resolve, reject) => {
switch(this.state){
case FULFILLED:
setTimeout(() => {
try{
let x = onFulfilled(this.value)
resolvePromise(promise, x, resolve, reject)
} catch(e){
reject(e)
}
})
break
case REJECTED:
setTimeout(() => {
try{
let x = onRejected(this.reason)
resolvePromise(promise, x, resolve, reject)
} catch(e){
reject(e)
}
})
break
default:
this.onResolvedCallbacks.push(() => {
setTimeout(() => {
try{
let x = onFulfilled(this.value)
resolvePromise(promise, x, resolve, reject)
} catch(e){
reject(e)
}
})
})
this.onRejectedCallbacks.push(() => {
setTimeout(() => {
try{
let x = onRejected(this.reason)
resolvePromise(promise, x, resolve, reject)
} catch(e){
reject(e)
}
})
})
}
})
return promise
}
catch(onRejected){
return this.then(null, onRejected)
}
finally(cb){
return this.then(
(y) => {
return Promise.resolve(cb()).then(() => y)
},
(r) => {
return Promise.resolve(cb()).then(() => {throw r})
}
)
}
static rsolve(value){
return new Promise((resolve,reject)=>{
resolve(value);
})
}
static reject(reason){
return new Promise((resolve,reject)=>{
reject(reason);
})
}
static all (promsies){
return new Promise((resolve, reject) => {
const arr = []
let count = 0
const processResult = (i, val) => {
arr[i] = val
if(++times === promises.length) resolve(arr)
}
for(let i = 0; i < promises.length; i++){
let val = promises[i]
if(typeof val.then === 'function'){
val.then(y => processResult(i, y), reject)
}else{
processResult(i, val)
}
}
})
}
}
Promise.race
实现原理
Promise.race
方法也是Promise
的静态方法,它的参数也是一个Promise
数组。只不过与Promise.all
方法不同的是,Promise.all
的作用是所有成功才是成功,有一个失败就失败。Promise.race
的作用是采用最快完成的Promise的结果作为最终的结果。
Promise.race
采用最快完成的Promsie
的结果作为结果,但是并不会中断其他Promise
的执行,只是不采用其他的结果了,没有中断效果。Promsie.all
的特点是全成功才成功,有一个失败了,其他的Promsie
也还是执行的。
- 原理实现
static race(promises) {
return new Promsie((resolve, reject)=>{
for(let i = 0; i < promise.length; i++){
let p = promises[i]
Promise.resolve(p).then(resolve, reject)
}
})
}
整理
至此我们的Promsie
完成了resolve
、reject
、catch
、finally
、all
、race
这几个方法,现在的Promise
已经算是比较完善了。经过一番整理现在的Promise
长这样。
const PENDING = 'pending'
const FULFILLED = 'fulfilled'
const REJECTED = 'rejected'
const resolvePromise = (promise, x, resolve, reject) => {
//*******************************************************判断x与promsie是否是同一个promise,防止进入死循环*********************//////*********
if(x === promise) throw new TypeError('Chaining cycle detected for promise #<Promise>')
// 1.首先判断`x`是基础类型数据,还是引用类型,基础类型的数据直接`resolve`,即可。
if(x !== null && /^(object|function)$/.test(typeof x)){
let then
// 2. 如果是引用类型的数据,尝试获取`x`上的`then`属性(`x.then`),如果在获取属性的时候报异常则`reject`
try{
then = x.then
}catch(e){
reject(e)
}
//3. 判断`then`是否是函数,如果是一个函数则我们认定它为`Promise`,如果不是则`resolve`
if(typeof then === 'function'){
let called = false //**************************************这里加了变量*************************//////
try{
then.call(x, (y) => {
if(called) return //**************************************这里加了变量*************************//////
called = true
resolvePromise(promise, y, resolve, reject)
},(r) => {
if(called) return//**************************************这里加了变量*************************//////
reject(r)
})
}catch(e){
if(called) return//**************************************这里加了变量*************************//////
reject(e)
}
}else{
resolve(x)
}
}else{
//基础类型数据直接resolve
resolve(x)
}
}
class Promise{
constructor(executor){
this.state = PENDING
this.value = undefined
this.reason = undefined
//存放onFulfilled
this.onResolvedCallbacks = []
//存放onRejected
this.onRejectedCallbacks = []
const resolve = (value) => {
//如果发现value是一个Promise,我们需要调用value的then方法去递归解析
if(value instanceof Promise){
return value.then(resolve,reject); // 递归解析
}
if (this.state === PENDING) {
this.value = value
this.state = FULFILLED
//promise实例状态改变后调用暂存的onFulfilled
this.onResolvedCallbacks.forEach(fn => fn())
}
}
const reject = (reason) => {
if (this.state === PENDING) {
this.reason = reason
this.state = REJECTED
//promise实例状态改变后调用的onRejected
this.onRejectedCallbacks.forEach(fn => fn())
}
}
try {
//executor函数执行过程中出错,将会导致Promise失败
executor(resolve,reject)
} catch (error) {
reject(error)
}
}
then(onFulfilled, onRejected){
onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : v => v
onRejected = typeof onRejected === 'function' ? onRejected : err => { throw err }
let promise = new Promise((resolve, reject) => {
switch(this.state){
case FULFILLED:
setTimeout(() => {
try{
let x = onFulfilled(this.value)
resolvePromise(promise, x, resolve, reject)
} catch(e){
reject(e)
}
})
break
case REJECTED:
setTimeout(() => {
try{
let x = onRejected(this.reason)
resolvePromise(promise, x, resolve, reject)
} catch(e){
reject(e)
}
})
break
default:
this.onResolvedCallbacks.push(() => {
setTimeout(() => {
try{
let x = onFulfilled(this.value)
resolvePromise(promise, x, resolve, reject)
} catch(e){
reject(e)
}
})
})
this.onRejectedCallbacks.push(() => {
setTimeout(() => {
try{
let x = onRejected(this.reason)
resolvePromise(promise, x, resolve, reject)
} catch(e){
reject(e)
}
})
})
}
})
return promise
}
catch(onRejected){
return this.then(null, onRejected)
}
finally(cb){
return this.then(
(y) => {
return Promise.resolve(cb()).then(() => y)
},
(r) => {
return Promise.resolve(cb()).then(() => {throw r})
}
)
}
static rsolve(value){
return new Promise((resolve,reject)=>{
resolve(value);
})
}
static reject(reason){
return new Promise((resolve,reject)=>{
reject(reason);
})
}
static all (promsies){
return new Promise((resolve, reject) => {
const arr = []
let count = 0
const processResult = (i, val) => {
arr[i] = val
if(++times === promises.length) resolve(arr)
}
for(let i = 0; i < promises.length; i++){
let val = promises[i]
if(typeof val.then === 'function'){
val.then(y => processResult(i, y), reject)
}else{
processResult(i, val)
}
}
})
}
static race(promises) {
return new Promsie((resolve, reject)=>{
for(let i = 0; i < promise.length; i++){
let p = promises[i]
Promise.resolve(p).then(resolve, reject)
}
})
}
}
传送门
从零手撕Promise,掌握Promise的实现原理(1)之promise基本结构的实现
从零手撕Promise,掌握Promise的实现原理(2)之基础版本的promise实现
从零手撕Promise,掌握Promise的实现原理(3)之回调地狱是什么
从零手撕Promise,掌握Promise的实现原理(4)之then方法链式调用的初步实现
从零手撕Promise,掌握Promise的实现原理(5)之then方法链式调用的进阶实现
从零手撕Promise,掌握Promise的实现原理(6)之then方法的回调为什么是异步微任务
从零手撕Promise,掌握Promise的实现原理(7)then方法链式调用之核心方法resolvePromise
从零手撕Promise,掌握Promise的实现原理(8)then方法链式调用之核心方法resolvePromise再探究
从零手撕Promise,掌握Promise的实现原理(9)then方法链式调用之核心方法resolvePromise完全体
从零手撕Promise,掌握Promise的实现原理(10)then方法完全体
从零手撕Promise,掌握Promise的实现原理(11)之测试完全体Promise是否符合PromiseA+
什么?Promise.resolve()还可以返回失败的Promise(12)