一、前言
大家都知道做前端开发的时候最让人头痛的就是处理异步请求的情况,在请求到的成功回调函数里继续写函数,长此以往形成了回调地狱。
1、对象的状态不受外界影响。Promise 对象代表一个异步操作,有三种状态:
- pending: 初始状态,不是成功或失败状态。
- fulfilled: 意味着操作成功完成。
- rejected: 意味着操作失败。
只有异步操作的结果,可以决定当前是哪一种状态,任何其他操作都无法改变这个状态。这也是 Promise 这个名字的由来,它的英语意思就是「承诺」,表示其他手段无法改变。
2、一旦状态改变,就不会再变,任何时候都可以得到这个结果。Promise 对象的状态改变,只有两种可能:从 Pending 变为 Resolved 和从 Pending 变为 Rejected。只要这两种情况发生,状态就凝固了,不会再变了,会一直保持这个结果。就算改变已经发生了,你再对 Promise 对象添加回调函数,也会立即得到这个结果。这与事件(Event)完全不同,事件的特点是,如果你错过了它,再去监听,是得不到结果的。
二、手写一个promise
class myPromise {
// promise 有三种状态未处理的、成功的、失败的
static PENDING = 'pending'
static FULFILL = 'fulfill'
static REJECT = 'REJECT'
constructor(result) {
// 初始状态
this.state = myPromise.PENDING
this.value = null;
// 当出现错误的时候需要补货
try {
// 当我们new一个对象的时候,this的指向被引向全局。window需要更改使用方向
result(this.resolve.bind(this), this.reject.bind(this))
} catch (err) {
this.reject(err)
}
}
resolve(value) {
// 因为结果是不可逆的需要判断
if (this.state === 'pending') {
this.state = myPromise.FULFILL
this.value = value
}
}
reject(reason) {
if (this.state === 'pending') {
this.state = myPromise.REJECT
this.reason = reason
}
}
}
在写一个then方法,这个时候写的promise并不是异步方法。
// then有成功与失败的回调
then(succeed, fail) {
// 当succeed与fail不是函数会出现报错
if (typeof (succeed) !== 'function') {
succeed = () => {}
}
if (typeof (fail) !== 'function') {
fail = () => {}
}
// 判断失败或是成功
if (this.state === myPromise.FULFILL) {
// 当有错误的时候需要捕获错误
try {
succeed(this.value)
} catch (err) {
console.log(err);
}
} else if (this.state === myPromise.REJECT) {
try {
fail(this.value)
} catch (err) {
console.log(err);
}
}
}
添加定时器将这个方法放入任务队列
then(succeed, fail) {
// 当succeed与fail不是函数会出现报错
if (typeof (succeed) !== 'function') {
succeed = () => {}
}
if (typeof (fail) !== 'function') {
fail = () => {}
}
// 判断失败或是成功
if (this.state === myPromise.FULFILL) {
setTimeout(() => {
// 当有错误的时候需要捕获错误
try {
succeed(this.value)
} catch (err) {
console.log(err);
}
}, 0)
} else if (this.state === myPromise.REJECT) {
setTimeout(() => {
try {
fail(this.value)
} catch (err) {
console.log(err);
}
}, 0);
}
}
处理链式操作,在构造函数里面添加一个callback数组,在状态改变后提取出状态一步步执行
// then有成功与失败的回调
then(succeed, fail) {
// 当succeed与fail不是函数会出现报错
if (typeof (succeed) !== 'function') {
succeed = () => {}
}
if (typeof (fail) !== 'function') {
fail = () => {}
}
// 通过递归实现链式操作
return new myPromise((resolve, reject) => {
// 执行到这里的时候状态为pending
if (this.state === myPromise.PENDING) {
this.callback.push({
succeed: value => {
// 当发生错误时交给错误结果统一处理
try {
//链式结果的状态需要放回给下一个
let result = succeed(value)
resolve(result)
} catch (error) {
fail(error)
}
},
fail: value => {
try {
//链式结果的状态需要放回给下一个
let result = fail(value)
resolve(result)
} catch (error) {
fail(error)
}
}
})
}
// 判断失败或是成功
if (this.state === myPromise.FULFILL) {
setTimeout(() => {
// 当有错误的时候需要捕获错误
try {
//链式结果的状态需要放回给下一个
let result = succeed(this.value)
resolve(result)
} catch (err) {
console.log(err);
}
}, 0)
} else if (this.state === myPromise.REJECT) {
setTimeout(() => {
try {
//链式结果的状态需要放回给下一个
let result = fail(this.value)
resolve(result)
} catch (err) {
console.log(err);
}
}, 0);
}
})
}
完整代码
class myPromise {
// promise 有三种状态未处理的、成功的、失败的
static PENDING = 'pending'
static FULFILL = 'fulfill'
static REJECT = 'REJECT'
constructor(result) {
// 初始状态
this.state = myPromise.PENDING
this.value = null;
this.callback = [];
// 当出现错误的时候需要补货
try {
// 当我们new一个对象的时候,this的指向被引向全局。window需要更改使用方向
result(this.resolve.bind(this), this.reject.bind(this))
} catch (err) {
this.reject(err)
}
}
resolve(value) {
// 因为结果是不可逆的需要判断
if (this.state === 'pending') {
this.state = myPromise.FULFILL
this.value = value
// 状态改变后在数组里面使用
// 因为需要一直在异步操作
setTimeout(() => {
this.callback.map(item => {
item.succeed(value)
})
}, 0);
}
}
reject(reason) {
if (this.state === 'pending') {
this.state = myPromise.REJECT
this.reason = reason
// 状态改变后在数组里面使用
setTimeout(() => {
this.callback.map(item => {
item.fall(reason)
})
}, 0);
}
}
// then有成功与失败的回调
then(succeed, fail) {
// 当succeed与fail不是函数会出现报错
if (typeof (succeed) !== 'function') {
succeed = () => {}
}
if (typeof (fail) !== 'function') {
fail = () => {}
}
// 通过递归实现链式操作
return new myPromise((resolve, reject) => {
// 执行到这里的时候状态为pending
if (this.state === myPromise.PENDING) {
this.callback.push({
succeed: value => {
// 当发生错误时交给错误结果统一处理
try {
//链式结果的状态需要放回给下一个
let result = succeed(value)
resolve(result)
} catch (error) {
fail(error)
}
},
fail: value => {
try {
//链式结果的状态需要放回给下一个
let result = fail(value)
resolve(result)
} catch (error) {
fail(error)
}
}
})
}
// 判断失败或是成功
if (this.state === myPromise.FULFILL) {
setTimeout(() => {
// 当有错误的时候需要捕获错误
try {
//链式结果的状态需要放回给下一个
let result = succeed(this.value)
resolve(result)
} catch (err) {
console.log(err);
}
}, 0)
} else if (this.state === myPromise.REJECT) {
setTimeout(() => {
try {
//链式结果的状态需要放回给下一个
let result = fail(this.value)
resolve(result)
} catch (err) {
console.log(err);
}
}, 0);
}
})
}
}