书接上文,实现静态方法
实现promise.all
该方法时静态方法,接受一个数组,根据数组顺序去返回一个结果
该方法返回一个promise对象可以链式调用then
如果all方法中有任何一个元素执行失败,那么all最终结果就是失败
const p1 = new Promise((resolve, reject) => {resolve('p1')})
const p2 = new Promise((resolve, reject) => {resolve('p2')})
Promise.all([1,'a', p1, 'b', p2]).then(response => {
// response --- [1,'a', 'p1', 'b', 'p2'] p1 和 p2 是执行结果
})
下面我们基于 Mypromise.all
Class Mypromise{
constructor() {}
// 静态方法用static 声明
// all接受一个数组array;
static all(array) {
// 循环遍历数组每一项
// 判断数组的每个元素,如果当前元素是普通值,应该传递出去
// 如果是promise 对象应该得到promise对象执行结果
// - 声明一个result 用来当作响应数据
let result = [];
for(var i = 0; i< array.length; i++) {
if (array[i] instanceof Mypromise) {
// promise对象
// 执行结果是成功 用resolve函数响应出去
// 执行结果是失败 用reject函数发送失败小心
array[i].then(response=> {}, errmessage=> {})
} else {
// 普通值
result[i] = array[i]
}
// 如果走到最后说明result中的值都是成功的响应
// 直接resolve(result)
resolve(result)
}
return new Mypromise((resolve, reject) => { })// all 返回了一个promise对象
}
}
}
因此循环要写在 Mypromise的执行器当中
let result = [];
return new Mypromise((resolve, reject) => { })// all 返回了一个promise对象
// 循环遍历数组每一项
// 判断数组的每个元素,如果当前元素是普通值,应该传递出去
// 如果是promise 对象应该得到promise对象执行结果
// - 声明一个result 用来当作响应数据
for(var i = 0; i< array.length; i++) {
if (array[i] instanceof Mypromise) {
// promise对象
// 执行结果是成功 用resolve函数响应出去
// 执行结果是失败 用reject函数发送失败小心
array[i].then(response=> {
result[i] = response
}, errmessage=> {
// 调用reject
reject(errmessage)
})
} else {
// 普通值
result[i] = array[i]
}
// 如果走到最后说明result中的值都是成功的响应
// 直接resolve(result)
resolve(result)
}
}
const p1 = new Mypromise((resolve, reject) => {
// throw new Error('executor错误')
resolve('p1')
})
const p2 = new Mypromise((resolve, reject) => {
// throw new Error('executor错误')
resolve('p2')
})
Mypromise.all([1,2,p1,'1-',p2, 0]).then(response => {
console.log(response)
})
// 打印结果是什么??
//
emm // [1, 2, 空, '1-', 空, 0, 'p2'] 数组长度也错了
因为for循环用var 声明了变量, 并且then中使用了setTimeout。 循环完成后i = 6. 由于setTimout, 因此会有result由 // [1, 2, 空, '1-', 空, 0, 'p1'] ====》变成 [1, 2, 空, '1-', 空, 0, 'p2']的过程
// 这里用let声明i即可
for(let i = 0; i< array.length; i++) {
if (array[i] instanceof Mypromise) {
// promise对象
// 执行结果是成功 用resolve函数响应出去
// 执行结果是失败 用reject函数发送失败小心
array[i].then(response=> {
result[i] = response
}, errmessage=> {
// 调用reject
reject(errmessage)
})
} else {
// 普通值
result[i] = array[i]
}
// 打印结果
//[1, 2, 'p1', '1-', 'p2', 0]
如果p1是异步的操作呢
const p1 = new Mypromise((resolve, reject) => {
// throw new Error('executor错误')
setTimeout(() => resolve('p1'), 0) // 0s后返回执行resolve p1
})
const p2 = new Mypromise((resolve, reject) => {
// throw new Error('executor错误')
resolve('p2')
})
Mypromise.all([1,2,p1,'1-',p2, 0]).then(response => {
console.log(response)
})
// [1, 2, 空, '1-', 'p2', 0]
// 分析下
// all 执行时 p1时pendding状态 p2时fulfille状态
// then执行是 由于状态问题 p1是异步完成后才resolve后执行this.successCallback p2是successFn中执行
// for循环是同步的 因此array[i] 如果时p1 还没执行完就 执行了resolve(result); 所以我们应该确保循环i当前有值,才进行resolve
// 定义一个模块级变量
let index = 0;
return new Mypromise((resolve, reject) => {
// 循环遍历数组每一项
// 判断数组的每个元素,如果当前元素是普通值,应该传递出去
// 如果是promise 对象应该得到promise对象执行结果
array[i].then(response=> {
result[i] = response
// 每次添加到result后index++
index++
// 如果index最后和array.lengh相同
index===array.length && resolve(result)
}
// 普通值
result[i] = array[i]
// 每次添加到result后
index++
}
}
// 如果走到最后说明result中的值都是成功的响应
// 直接resolve(result)
// 如果index最后和array.lengh相同
index===array.length && resolve(result)
}
//
Mypromise.all([1,2,p1,'1-',p2, 0]).then(response => {
console.log(response)
})
// [1, 2, 'p1', '1-', 'p2', 0]
Promise.resolve
Promise.resolve返回一个promise,并且将给定的值传递给下一个then进行链式调用
如给的值是一个promise 将promisef返回就行
static resolve(value) {
if (value instanceof Mypromise) value;
return new Mypromise((resolve) => resolve(value))
}
Mypromise.resolve('1').then(val => console.log(val)) // '1'
Mypromise.resolve(p1).then(val => console.log(val)) // 'p1'
finally
finally 回调会被执行依次, 然后可以链式调用then
finally方法属于实例方法
--javascripttypescriptbashsqljsonhtmlcssccppjavarubypythongorustmarkdown
let p1 = new Promise((resolve, reject) => {
resolve('hello')
})
p1.finally(() => {
console.log('执行回调')
}).then(res => {
console.log(res) // 拿到p1的结果去then调用
})
------
finally(callback) {
// 通过then知道promise的状态
// then的成功回调和失败回调都要执行一次callback
// finally方法可以链式调用说明返回了;而then方法也是返回了promise 所以return this.then就好
return this.then((response)=> {
callback()
return response // response就是当前this promise当前的响应
}, (errmessage)=> {
callback()
// 如果失败就抛出errerrmessage
throw errmessage
})
}
const p2 = new Mypromise((resolve, reject) => {
// throw new Error('executor错误')
reject('p2失败')
})
p2.finally(() => {
console.log('finally') // finally
}).then(response => {
console.log(response)
}, errmessage => {
console.log(errmessage) // p2失败
})
在finally中可以进行return 一个结果,如果return的是一个promise 会等该promise结果完成后then执行then
const p1 = new Mypromise((resolve, reject) => {
// throw new Error('executor错误')
setTimeout(() => {
console.log('p1执行')
resolve()
}, 100) // 0s后返回执行resolve p1
})
const p2 = new Mypromise((resolve, reject) => {
// throw new Error('executor错误')
reject('p2失败')
})
p2.finally(() => {
console.log('finally')
return p1 //执行p1
}).then(response => {
console.log(response)
}, errmessage => {
console.log(errmessage) // 失败
})
//
finally(callback) {
return this.then((response)=> {
// 通过promise.resolve传入callback 实际上 相当于 返回的是p1.then() 去执行p1之后再去用p2执行结果去then
return Mypromise.resolve(callback()).then(() => response)
// callback()
// return response // response就是当前this promise当前的响应
}, (errmessage)=> {
// 同理
return Mypromise.resolve(callback()).then(() => {throw errmessage})
// callback()
// // 如果失败就抛出errerrmessage
// throw errmessage
})
}
catch 错误捕获
catch(failureCallback) {
// 调用then 成功回调传uundefined
// 失败回调就是callback 调用catch时实际上就是调用then中的失败回调
return this.then(undefined, failureCallback)
}
const p2 = new Mypromise((resolve, reject) => {
// throw new Error('executor错误')
reject('p2')
})
p2.then((res) => {
console.log('res')
}).catch(res => {
console.log(res)
})
// 打印 TypeError: failureFn is not a function
// 分析'P2'才对
p2是失败的状态, 当执行到then中缺没有失败回调。那么自然就发生了错误
还记
p2是失败状态rejected, 当执行then方法, 里面没有失败回调,只有成功回调。自然发生了错误
还记得第1篇中的then穿透吗我们当时给成功回调设置了默认值
对于失败回调呢
--javascripttypescriptbashsqljsonhtmlcssccppjavarubypythongorustmarkdown
successFn = successFn ? successFn : value => value // 补参如果有参数就用 如果没有参数就是一个函数
failureFn = failureFn ? failureFn : value => {throw value} // 如果没有失败回调那么就 throw reject的消息
p2.then((res) => {
console.log('res')
},
value => {throw value} // 相当与添加了一个错误信息 抛出一一个错误。被错误处理捕获到reject()
).catch(res => { // 到这里then成功回调是null, 失败回调时 res=> {log(res)}
console.log(res)
})
下面时所有代码
// 首先设置三种状态常量
const PENDDING = 'pendding';
const FULFILLED = 'fulfilled';
const REJECTED = 'rejected'
class Mypromise {
constructor(executor) {
// new promise是会立即执行执行器,并且接受两个参数, resolve函数和reject函数
// 执行器执行时发生了错误用try cathch去捕获执行器执行
try {
executor(this.resolve, this.reject)
} catch (e) {
// 如果有错误直接执行reject
this.reject(e)
}
}
status = PENDDING;
response = undefined // 定义一个成功的响应值
errmessage = undefined // 失败的信息
// 首先我们用属性succcessCallback存储successFn 和 failureCallback存储failureFn
succcessCallback = [];
failureCallback = [];
// resolve是一个函数, 参数是响应值
resolve = (response) => {
if(this.status !== PENDDING ) return
this.status = FULFILLED;
this.response = response; // 缓存成功消息
// 当异步操作2s后执行到resolve的时候 如果succcessCallback 存在那么执行succcessCallback
//this.succcessCallback && this.succcessCallback(this.response)
while (this.succcessCallback.length) {
this.succcessCallback.shift()()
}
}
// reject也是一个函数, 参数是错误消息
reject= (errmessage) => {
if(this.status !== PENDDING ) return
this.status = REJECTED;
this.errmessage = errmessage // 缓存失败信息
// 当异步操作2s后执行到reject的时候 如果failureCallback 存在那么执行failureCallback
//this.failureCallback && this.failureCallback (this.errmessage )
while (this.failureCallback.length) {
this.failureCallback.shift()()
}
}
then = (successFn, failureFn) => {
successFn = successFn ? successFn : value => value // 补参如果有参数就用 如果没有参数就是一个函数
failureFn = failureFn ? failureFn : value => {throw value}
// 获取到promise
let pr = new Mypromise((resolve, reject) => {
// 当前状态成功了执行successFn
// 当前状态失败了执行 failureFn
if(this.status === FULFILLED) {
// 加入异步代码让它在pr生成后去用pr
setTimeout(() => {
// then中发生了错误 也用try catch捕获
try {
let res = successFn(this.response) // 执行成功的回调 参数是成功的响应数据
resolvePromise(pr, res, resolve, reject) // 处理成功时结果
} catch(e) {
reject(e)
}
}, 0)
} else if (this.status === REJECTED) {
setTimeout(() => {
// then中发生了错误 也用try catch捕获
try {
let res = failureFn(this.errmessage) // 执行失败的回调 参数是失败的信息
resolvePromise(pr, res, resolve, reject) // 处理失败时结果
} catch(e) {
reject(e)
}
}, 0)
} else {
// 如果是pendding状态我们首先储存succcessCallback 和 failureCallback
// this.succcessCallback.push(successFn);
// this.failureCallback.push(failureFn);
// 这里以前我们是通过push的方法存储回调 如果then中的异步,我们就要push 一个函数了。
this.succcessCallback.push(() => {
// 如果是成功去执行成功的代码
setTimeout(() => {
// then中发生了错误 也用try catch捕获
try {
let res = successFn(this.response) // 执行成功的回调 参数是成功的响应数据
resolvePromise(pr, res, resolve, reject) // 处理成功时结果
} catch(e) {
reject(e)
}
}, 0)
})
this.failureCallback.push(() => {
setTimeout(() => {
// then中发生了错误 也用try catch捕获
try {
let res = failureFn(this.errmessage) // 执行失败的回调 参数是失败的信息
resolvePromise(pr, res, resolve, reject) // 处理失败时结果
} catch(e) {
reject(e)
}
}, 0)
});
}
})
return pr; // 返回一个promise
}
finally(callback) {
return this.then((response) => {
return Mypromise.resolve(callback()).then(() => response)
// callback()
// return response
}, (errmessage) => {
return Mypromise.resolve(callback()).then(() => {throw errmessage})
})
}
catch(failCallback) {
return this.then(undefined, failCallback)
}
// all接受一个数组array;
static all(array) {
// 循环遍历数组每一项
// 判断数组的每个元素,如果当前元素是普通值,应该传递出去
// 如果是promise 对象应该得到promise对象执行结果
// - 声明一个result 用来当作响应数据
let result = [];
let index = 0
// all 返回了一个promise对象
return new Mypromise((resolve, reject) => {
for(let i = 0; i< array.length; i++) {
if (array[i] instanceof Mypromise) {
// promise对象
// 执行结果是成功 用resolve函数响应出去
// 执行结果是失败 用reject函数发送失败小心
array[i].then(response=> {
result[i] = response
// 每次添加到result后index++
index++
// 如果index最后和array.lengh相同
index===array.length && resolve(result)
}, errmessage=> {
reject(errmessage)
})
} else {
// 普通值
result[i] = array[i]
index++
}
// 如果走到最后说明result中的值都是成功的响应
// 直接resolve(result)
index === array.leng && resolve(result)
}
})
}
static resolve(value) {
if (value instanceof Mypromise) value;
return new Mypromise((resolve, reject) => {resolve(value)})
}
}
// res是successFn执行的结果, resolve是成功的回调, reject是结束的回调
function resolvePromise(returnP, res, resolve, reject) {
console.log(res)
if (returnP === res) {
// 如果回调的promise 和 then中要返回的promise是同一个对象那么就发生了 循环调用。 直接return 阻止代码继续向下执行
return reject(new TypeError ('Chaining cycle detected for promise #<Promise>'))
}
if (res instanceof Mypromise) {
// 执行结果是一个promise
// 调用then方法拿到执行结果如果成功执行resolve
// 失败就调用reject
res.then(value => resolve(value), err => reject(err))
} else {
// 普通值直接调用resolve方法
resolve(res)
}
}
const p2 = new Mypromise((resolve, reject) => {
// throw new Error('executor错误')
reject('p2')
})
p2.then((res) => {
console.log('res')
}).catch(res => {
console.log(res)
})