# Promise 进阶
# Promise.resolve
这里就不考虑参数是thenable对象了,那么参数有两种情况:
- Promise 实例,直接返回
- 不是 Promise 实例,返回一个新的 Promise 对象,状态为
FULFILLED
Promise.resolve = function(param){
if (param instanceof MyPromise) {
return param
}
return new MyPromise((resolve, reject) => resolve(param))
}
# Promise.reject
Promise.reject
中传入的参数会作为一个 reason
原封不动地往下传, 实现如下:
Promise.reject = function(param){
return new MyPromise((resolve, reject) => reject(param))
}
# Promise.finally
无论当前 Promise
是成功还是失败,调用 finally
之后都会执行 finally
中传入的函数,并且将值原封不动的往下传。
Promise.finally = function(callback) {
this.then(value => {
return Promise.resolve(callback()).then(() => {
return value;
})
}, error => {
return Promise.resolve(callback()).then(() => {
throw error;
})
})
}
# Promise.all
返回一个 promise
对象,只有当所有 promise
都成功时返回的 promise
状态才成功,需要注意的点是:
- 数组成员不为
promise
,则直接进行resolve() - 所有的 promise 状态变为
FULFILLED
,返回的 promise 状态才变为FULFILLED
。 - 一个 promise 状态变为
REJECTED
,返回的 promise 状态就变为REJECTED
。 - 在任何情况下,Promise.all 返回的 promise 的完成状态的结果都是一个
数组
具体实现如下:
Promise.all = function(promises){
return new MyPromise((resolve, reject) => {
let result = [];
let len = promises.length;
if (len === 0) {
return resolve(result)
}
for (let i = 0; i < len; i++) {
Promise.resolve(promises[i]).then(res => {
result[i] = res
if (i == len - 1) { // 最后一个
resolve(result)
}
}).catch(err => {
reject(err)
})
}
})
}
# Promise.race
race 的实现相比之下就简单一些,只要有一个 promise 执行完,直接 resolve 并停止执行。
Promise.race = function(promises){
return new MyPromise((resolve, reject) => {
let len = promises.length;
if (len === 0) return
for (let i = 0; i < len; i++) {
Promise.resolve(promises[i]).then(res => {
resolve(res)
return
}).catch(err => {
reject(err)
return
})
}
})
}
到此为止,一个完整的 Promise
就被我们实现完啦。从原理到细节,我们一步步拆解和实现,希望大家在知道 Promise
设计上的几大亮点之后,也能自己手动实现一个 Promise
,让自己的思维层次和动手能力更上一层楼!
# Promise实现网络超时判断
使用Promise实现网络请求超时判断,超过三秒视为超时。 借助的是Promise.race这个方法:
const uploadFile = () => {
return Promise.race([
uploadFilePromise(),
uploadFileTimeout(3000)
])
}
function uploadFilePromise() {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve('OK')
}, 3100)
})
}
function uploadFileTimeout() {
return new Promise((resolve, reject) => {
setTimeout(() => {
reject('Time out ~~')
}, 3000)
})
}
uploadFile().then((res) => {
console.log(res)
}).catch((err) => {
console.log(err)
})