手写promise的代码如下:
class myPromise {
static PENDING = 'pending'
static FULFILLED = 'fulfilled'
static REJECTED = 'rejected'
static resolve (value) {
if (value && value.then) {
return value
}
return new myPromise((resolve) => resolve(value))
}
static reject (value) {
return new myPromise((_, reject) => reject(value))
}
constructor (fn) {
this.status = myPromise.PENDING
this.result = null
this.resFns = []
this.rejFns = []
const resolve = (value) => {
if (this.status === myPromise.PENDING) {
setTimeout(() => {
this.status = myPromise.FULFILLED
this.result = value
this.resFns.forEach(({fn, resolve, reject}) => resolve(fn(value)))
})
}
}
const reject = (reason) => {
if (this.status === myPromise.PENDING) {
setTimeout(() => {
this.status = myPromise.REJECTED
this.result = reason
this.rejFns.forEach(({fn, resolve, reject}) => reject(fn(reason)))
})
}
}
try {
fn(resolve, reject)
} catch (err) {
reject(err)
}
}
then (resFn, rejFn) {
resFn = typeof resFn === 'function' ? resFn : value => value
rejFn = typeof rejFn === 'function' ? rejFn : reason => reason
const _promise = {
[myPromise.PENDING]: () => {
return new myPromise((resolve, reject) => {
this.resFns.push({fn: resFn, resolve, reject})
this.rejFns.push({fn: rejFn, resolve, reject})
})
},
[myPromise.FULFILLED]: () => myPromise.resolve(resFn(this.result)),
[myPromise.REJECTED]: () => myPromise.reject(rejFn(this.result))
}[this.status]
return _promise()
}
catch (fn) {
return this.then(undefined, fn)
}
finally(cb) {
return this.then(cb, cb)
}
static all (iterable) {
return new myPromise((resolve, reject) => {
const arr = Array.from(iterable)
const result = []
let count = 0
arr.forEach((item, i) => {
myPromise.resolve(item).then(res => {
result[i] = res
count++
if (count === arr.length) {
resolve(result)
}
}).catch(err => reject(err))
})
})
}
}
// 用例1
// myPromise.resolve(10)
// .then(o => o * 10)
// .then(o => o + 10)
// .then(o => {
// console.log(o)
// })
// 用例2
// new myPromise((resolve, reject) => reject('报错了'))
// .then(e => {
// console.log('Error', e)
// })
// .catch(err => {
// console.log(err)
// })
// 用例3
// myPromise.all([123, Promise.resolve('hahah'), Promise.resolve('lalal')])
// .then(res => {
// console.log(res)
// })
// .catch(err => {
// console.log(err)
// })
// 用例4
// let p1 = new myPromise((resolve, reject) => {
// resolve(1)
// }).then((value) => {
// console.log(value)
// }).catch((e) => {
// console.log(e)
// }).finally(() => {
// console.log('finally')
// })
//用例5
console.log(1);
const promise = new myPromise((resolve, reject) => {
console.log(2);
setTimeout(() => {
resolve('success');
console.log(4);
}, 2000);
})
promise.then(value => {
console.log(11)
console.log('resolve', value)
return value
}).then((value) => {
console.log(22)
console.log('resolve', value)
})
console.log(3);
promise.all的特点:接受一个由promise对象组成的多项数组,当数组中的每一项都返回fulfilled,则才算当前的状态变更为fulfilled;
只要有一个抛出错误,变更为rejected,当前的状态才变更为rejected。
而且当全部成功后,返回的回调参数是按原数组的顺序返回的
手动实现的代码如下:
function PromiseAll (proArry) {
let result = []
let count = 0
return new Promise((resolve,reject) => {
for(let i=0;i<proArry.length;i++) {
Promise.resolve(proArry[i]).then(res => {
// 这里不用push是因为,每一个promise对象返回的时间可能有长有短
//为了按照原顺序输入,使用key的方式添加
// 定义count变量,而不直接使用result.length进行比较,也是如此
result[i] = res;
count++;
if(proArry.length === count) {
resolve(result)
}
}).catch(err => {
// 只要有一项抛出错误,就会调用new Promise的reject
reject(err)
})
}
})
}
js快排实现:
// 分区函数,负责把数组分按照基准值分为左右两部分
// 小于基准的在左侧,大于基准的在右侧最后返回基准值的新下标
function partition(arr, left, right) {
// 基准值可以是left与right之间的任意值,再将基准值移动至最左或最右即可。
// 直接基于中间位置排序,则需要基于中间位置左右交换,参加基于中间位置交换的版本。
// var tmpIndex = Math.floor((right - left) / 2)
// ;[arr[left + tmpIndex], arr[right]] = [arr[right], arr[left + tmpIndex]]
var pivotIndex = right
var pivot = arr[pivotIndex]
var partitionIndex = left - 1
for (var i = left; i < right; i++) {
// 如果比较项小于基准值则进行交换,并且分区索引增加1位
// 也就是将大于基准值的全部往右侧放,以分区索引为分割线
if (arr[i] < pivot) {
partitionIndex++
if (partitionIndex !== i) {
[arr[partitionIndex], arr[i]] = [arr[i], arr[partitionIndex]]
}
}
}
partitionIndex++;
[arr[partitionIndex], arr[pivotIndex]] = [arr[pivotIndex], arr[partitionIndex]]
return partitionIndex
}
// 分区递归版本,分区递归调用。
function quickSort2(arr, left, right) {
left = left !== undefined ? left : 0
right = right !== undefined ? right : arr.length - 1
if (left < right) {
var pivot = partition(arr, left, right)
quickSort2(arr, left, pivot - 1)
quickSort2(arr, pivot + 1, right)
}
return arr
}