前言
为解决回调地狱问题,提出了 Promise 对象,并且后来加入了 ES6 标准。
一、Promise是什么?
Promise对象的then方法返回新的Promise对象,支持链式调用,解决了回调地狱的问题。
二、手写Promise(构造函数版本)
function Promise (executor) {
this.PromiseState = 'pending'
this.PromiseResult = null
const self = this
this.callbacks = []
function resolve (data) {
if (self.PromiseState === 'pending') {
self.PromiseState = 'fulfilled'
self.PromiseResult = data
setTimeout(() => {
self.callbacks.forEach(item=>item.onresolved(data))
})
}
}
function reject (reason) {
if (self.PromiseState === 'pending') {
self.PromiseState = 'rejected'
self.PromiseResult = reason
setTimeout(() => {
self.callbacks.forEach(item=>item.onrejected(reason))
});
}
}
try {
executor(resolve,reject)
} catch (e) {
reject(e)
}
}
Promise.prototype.then = function (onresolved, onrejected) {
return new Promise((resolve, reject) => {
const self = this
if (typeof onrejected !== 'function') {
onrejected = reason => { throw reason }
}
if (typeof onresolved !== 'function') {
onresolved = value => value
}
const callback = function (type) {
try {
const result = type(self.PromiseResult)
if (result instanceof Promise) {
result.then(v => {
resolve(v)
}, r => {
reject(r)
})
} else {
resolve(result)
}
} catch (e) {
reject(e)
}
}
if (this.PromiseState === 'fulfilled') {
setTimeout(() => {
callback(onresolved)
})
}
if (this.PromiseState === 'rejected') {
setTimeout(() => {
callback(onrejected)
})
}
if (this.PromiseState === 'pending') {
this.callbacks.push({
onresolved: function () {
callback(onresolved)
},
onrejected: function () {
callback(onrejected)
}
})
}
})
}
Promise.prototype.catch = function (onrejected) {
return this.then(undefined,onrejected)
}
Promise.resolve = function (data) {
return new Promise((resolve, reject) =>{
if (data instanceof Promise) {
data.then(v => {
resolve(v)
}, r => {
reject(r)
})
} else {
resolve(data)
}
})
}
Promise.reject = function (data) {
return new Promise((resolve, reject) => {
reject(data)
})
}
Promise.all = function (promises) {
return new Promise((resolve, reject) => {
let count = 0
let result = []
for (let i = 0; i < promises.length; i++){
promises[i].then(v => {
count++
result[i] = v
if (count === promises.length) {
resolve(result)
}
}, r => {
reject(r)
})
}
})
}
Promise.race = function (promises) {
return new Promise((resolve, reject) => {
for (let i = 0; i < promises.length; i++){
promises[i].then(v => {
resolve(v)
}, r => {
reject(r)
})
}
})
}
三、手写Promise(class版本)
class Promise{
constructor(executor) {
this.PromiseState = 'pending'
this.PromiseResult = null
this.callbacks = []
const resolve= (data)=> {
if (this.PromiseState === 'pending') {
this.PromiseState = 'fulfilled'
this.PromiseResult = data
setTimeout(() => {
this.callbacks.forEach(item=>item.onresolved(data))
})
}
}
const reject = (reason)=> {
if (this.PromiseState === 'pending') {
this.PromiseState = 'rejected'
this.PromiseResult = reason
setTimeout(() => {
this.callbacks.forEach(item=>item.onrejected(reason))
});
}
}
try {
executor(resolve,reject)
} catch (e) {
reject(e)
}
}
then (onresolved, onrejected) {
return new Promise((resolve, reject) => {
const self = this
if (typeof onrejected !== 'function') {
onrejected = reason => { throw reason }
}
if (typeof onresolved !== 'function') {
onresolved = value => value
}
const callback = type=> {
try {
const result = type(self.PromiseResult)
if (result instanceof Promise) {
result.then(v => {
resolve(v)
}, r => {
reject(r)
})
} else {
resolve(result)
}
} catch (e) {
reject(e)
}
}
if (this.PromiseState === 'fulfilled') {
setTimeout(() => {
callback(onresolved)
})
}
if (this.PromiseState === 'rejected') {
setTimeout(() => {
callback(onrejected)
})
}
if (this.PromiseState === 'pending') {
this.callbacks.push({
onresolved: function () {
callback(onresolved)
},
onrejected: function () {
callback(onrejected)
}
})
}
})
}
catch (onrejected) {
return this.then(undefined,onrejected)
}
static resolve(data) {
return new Promise((resolve, reject) =>{
if (data instanceof Promise) {
data.then(v => {
resolve(v)
}, r => {
reject(r)
})
} else {
resolve(data)
}
})
}
static reject(data) {
return new Promise((resolve, reject) => {
reject(data)
})
}
static all(promises) {
return new Promise((resolve, reject) => {
let count = 0
let result = []
for (let i = 0; i < promises.length; i++){
promises[i].then(v => {
count++
result[i] = v
if (count === promises.length) {
resolve(result)
}
}, r => {
reject(r)
})
}
})
}
static race(promises) {
return new Promise((resolve, reject) => {
for (let i = 0; i < promises.length; i++){
promises[i].then(v => {
resolve(v)
}, r => {
reject(r)
})
}
})
}
}