Promise
是异步编程的一种解决方案: 从语法上讲, promise
是一个对象,从它可以获取异步操作的消息; 从本意上讲, 它是承诺, 承诺它过一段时间会给你一个结果
promise有三种状态: pending
(等待态), fulfiled
(成功态), rejected
(失败态); 状态一旦改变, 就不会再变; 创造promise实例后, 它会立即执行
Promise的实现
class MyPromise {
constructor(fn) {
this.resolvedCallbacks = []
this.rejectedCallbacks = []
this.state = 'PENDING'
this.value = ''
fn(this.resolve.bind(this), this.reject.bind(this))
}
resolve(value) {
if (this.state === 'PENDING') {
this.state = 'RESOLVED'
this.value = value
this.resolvedCallbacks.map(cb => cb(value))
}
}
reject(value) {
if (this.state === 'PENDING') {
this.state = 'REJECTED'
this.value = value
this.rejectedCallbacks.map(cb => cb(value))
}
}
then(onFulfilled, onRejected) {
if (this.state === 'PENDING') {
this.resolvedCallbacks.push(onFulfilled)
this.rejectedCallbacks.push(onRejected)
}
if (this.state === 'RESOLVED') {
onFulfilled(this.value)
}
if (this.state === 'REJECTED') {
onRejected(this.value)
}
}
}
Promise.all
Promise.all = function(arr) {
return new Promise((resolve, reject) => {
if(!Array.isArray(arr)) {
throw new TypeError(`argument must be a array`)
}
let length = arr.length
let resolveNum = 0
let resolveResult = []
for (let i = 0; i < length; i++) {
arr[i].then(data => {
resolveNum++
resolveResult.push(data)
if (resolveNum === length) {
return resolve(resolveResult)
}
}).catch(data => {
return reject(data)
})
}
})
}
Promise.race
Promse.race
就是赛跑的意思, 意思就是说,Promise.race([p1, p2, p3])
里面哪个结果获得的快, 就返回那个结果, 不管结果本身是成功状态还是失败状态Promise.race
方法里的参数不一定都是promise, 当不是promise的时候会把它转换为promise
Promise.race = function(arr) {
if (!Array.isArray(arr)) {
throw new typeError('argument must be array')
}
return new Promise((resolve, reject) => {
for(let i = 0; i < arr.length; i++) {
Promise.resolve(arr[i]).then(val => resolve(val), err => reject(err))
}
})
}
Promise.retry
promise.retry
的作用是执行一个函数, 如果不成功最多可以尝试times次.传参需要三个变量, 所要执行的函数, 尝试的次数以及间隔尝试的时间
Promise.retry = function(fn, times, delay) {
return new Promise((resolve, reject) => {
let error
let attemp = function() {
if (times == 0) {
reject(error)
} else {
fn().then(resolve)
.catch(e => {
times--
error = e
setTimeout(function(){attempt()}, delay)
})
}
}
attemp()
})
}