回调地狱
首先 回调地狱 本身不是一个错误,例如
// 等上一个ajax完成,并获取到结果再执行下一个ajax
First(function(r1){
Second(r1, function(r2){
Third(r2, function(r3){
console.log(r3);
})
})
})
只是回调地狱带来了不好的影响:不便于阅读, 不便于异常处理
解决方法
这时,可以利用 promise 链式调用来解决回调地狱问题,例如:
First().then(function(r1) { //r1是First函数成功执行的返回值
return Second(r1) //执行器函数,同步回调
})
.then(function(r2){ //r2是Second成功执行的返回值
return Third(r2)
})
.then(function(r3){
console.log(r3)
})
.catch(failureCallback) //统一的错误处理
promise的链式调用虽然解决了回调地狱和错误的统一处理,但是还有回调函数。
最优解决方法 :
async/await
async function request() {
try{
const r1= await First()
const r2= await Second(result)
const r3= await Third(newResult)
console.log(r3)
} catch (error) {
failureCallback(error)
}
}
最后附上 promise链式调用 的源码:
// Promise的链式调用
// 实现resolvePromise 对值进行判断 判断是普通值还是promise
const PENDING = 'PENDING',
FULFILLED = 'FULFILLED',
REJECTED = 'REJECTED';
function resolvePromise(promise2, x, resolve, reject) {
if (promise2 === x) { // 如果promise和x指向同一对象,promise则以拒绝TypeError为理由。
return reject(new TypeError('clean exit - waiting for changes before restart'))
}
let called = false // 防止多次调用resolve,只调用第一个resolve
if ((typeof x === 'object' && x != null) || typeof x === 'function') {
try {
let then = x.then //如果没有.then会导致throw error
if (typeof then === 'function') { // 认定为一个promise
then.call(x, (y) => {
if (called) {
return
}
called = true
resolvePromise(promise2, y, resolve, reject) // 当then里return promise时递归调用promise
}, (r) => {
if (called) {
return
}
called = true
reject(r)
})
} else {
resolve(x)
}
} catch (e) {
if (called) {
return
}
called = true
reject(e)
}
} else { // 普通值
resolve(x)
}
}
class MyPromise {
constructor(executor) {
this.status = PENDING
this.value = undefined
this.reason = undefined
this.onFulfilledCallbacks = [] // 成功的回调函数
this.onRejectedCallbacks = [] // 失败的回调函数
const resolve = (value) => {
if (this.status === PENDING) {
this.status = FULFILLED
this.value = value
//发布
this.onFulfilledCallbacks.forEach(fn => fn())
}
}
const reject = (reason) => {
if (this.status === PENDING) {
this.status = REJECTED
this.reason = reason
//发布
this.onRejectedCallbacks.forEach(fn => fn())
}
}
try {
executor(resolve, reject)
} catch (e) {
reject(e)
}
}
// x: 普通值 || promise
then(onFulfilled, onRejected) {
// 穿透.then().then().then().then().then().then((value))
onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : (value) => {
return value
}
onRejected = typeof onRejected === 'function' ? onRejected : (reason) => {
throw reason
}
let promise2 = new MyPromise((resolve, reject) => {
if (this.status === FULFILLED) {
// 利用setTimeout来实现宏任务的异步执行,等new完以后才执行里面的内容
setTimeout(() => {
try {
let x = onFulfilled(this.value)
resolvePromise(promise2, x, resolve, reject)
} catch (e) {
reject(e)
}
}, 0)
}
if (this.status === REJECTED) {
setTimeout(() => {
try {
let x = onRejected(this.reason)
resolvePromise(promise2, x, resolve, reject)
} catch (e) {
reject(e)
}
}, 0)
}
// 订阅
// setTimeout时还没进入fulfilled和rejected的状态,此时为pending
// 利用订阅和发布的模式,先将要执行的方法存起来,到fulfilled和rejected的状态时再执行。
if (this.status === PENDING) {
this.onFulfilledCallbacks.push(() => {
try {
let x = onFulfilled(this.value)
resolvePromise(promise2, x, resolve, reject)
} catch (e) {
reject(e)
}
})
this.onRejectedCallbacks.push(() => {
try {
let x = onRejected(this.reason)
resolvePromise(promise2, x, resolve, reject)
} catch (e) {
reject(e)
}
})
}
})
return promise2
}
catch (errorCallback) { // 防止.catch is not a function
return this.then(null, errorCallback)
}
}