Callback Hell回调地狱
方法一层层的嵌套,就形成回调地狱,类似下面这种:
function ajax (url, callback) {
// 1.创建XMLHttpRequest对象
var xmlHttp
if (window.XMLHttpRequest) {
xmlHttp = new XMLHttpRequest()
} else { //兼容早期ie浏览器
xmlHttp = new ActiveXObject('Microsoft.XMLHTTP')
}
// 2.发送请求
xmlHttp.open('GET', url, true)
xmlHttp.send()
// 服务端响应
xmlHttp.onreadystatechange = function () {
if (xmlHttp.readState === 4 && xmlHttp.status === 200) {
var obj = JSON.parse(xmlHttp.responseText)
callback(obj)
}
}
}
/* var url = '******'
ajax(url, res => {
console.log(res)
}) */
// 回调地狱
ajax('../static/a.json', resA => {
console.log(resA)
ajax('../static/b.json', resB => {
console.log(resB)
ajax('../static/c.json', resC => {
console.log(resC)
})
})
})
回调地狱这种代码耦合性高,不太好
Promise异步编程
Promise可以解决回调地狱的问题,将代码扁平化,将一层一层嵌套的模式变为同级关系
Promise用法如下:
eg:
var p = new Promise((resolve, reject) => {
// 异步处理程序
}).then(res => {
// 执行成功状态
}, err => {
// 执行失败状态
})
参数规定这么写:(resolve, reject)
resolve- - -成功状态参数
reject- - -失败状态参数
可以不两个参数都写
使用 then() 函数进行异步结果处理,可以写两个函数,第一个是执行成功的处理函数,第二个是执行失败的处理函数,第二个可以省略不写
还可以用 catch() 函数进行失败捕获
Promise程序处理状态
- pending- - -进行中
- fulfilled- - -成功状态
- rejected- - - 失败状态
处理完之后就是成功或者失败状态,状态确定之后,不再改变
eg: resolve()模拟状态成功后,再用reject()尝试更改状态为失败,但是更改无效

Promise使用代码示例:
Promise处理上面的回调地狱问题:
普通写法1:
function ajax (url, successCallback, failCallback) {
// 1.创建XMLHttpRequest对象
var xmlHttp
if (window.XMLHttpRequest) {
xmlHttp = new XMLHttpRequest()
} else { //兼容早期ie浏览器
xmlHttp = new ActiveXObject('Microsoft.XMLHTTP')
}
// 2.发送请求
xmlHttp.open('GET', url, true)
xmlHttp.send()
// 服务端响应
xmlHttp.onreadystatechange = function () {
if (xmlHttp.readState === 4 && xmlHttp.status === 200) {
var obj = JSON.parse(xmlHttp.responseText)
successCallback && successCallback(obj)
} else if(xmlHttp.readState === 4 && xmlHttp.status === 404) {
failCallback && failCallback(xmlHttp.statusText)
}
}
}
var p1 = new Promise((resolve, reject) => {
ajax('../static/a.json', res => {
console.log(res)
resolve()
})
}).then(res => {
console.log('a成功')
return new Promise((resolve, reject) => {
ajax('../static/b.json', res => {
console.log(res)
resolve()
})
})
}).then(res => {
console.log('b成功')
return new Promise((resolve, reject) => {
ajax('../static/c.json', res => {
console.log(res)
resolve()
})
})
}).then(res => {
console.log('c成功')
})
可以将Promise封装成函数使用:
①使用then() 第二个函数捕获异常err
// then() 第二个函数捕获异常err
getPromise('../static/a.json').then(res => {
console.log('a成功: ' + res)
return getPromise('../static/b.json')
}, err => {
console.log('失败'+ err)
return getPromise('../static/b.json')
}).then(res => {
console.log('b成功: ' + res)
return getPromise('../static/c.json')
}).then(res => {
console.log('c成功: ' + res)
})
②catch() 捕获异常
// catch() 捕获异常
getPromise('../static/a.json').then(res => {
console.log('a成功: ' + res)
return getPromise('../static/b.json')
}).then(res => {
console.log('b成功: ' + res)
return getPromise('../static/c.json')
}).then(res => {
console.log('c成功: ' + res)
}).catch(err => {
console.log(err)
})
Promise实例方法
new Promise((resolve, reject) => {、、、}).then(、、、).cathch(、、、)
.then() .catch() 是实例方法
Promise静态方法
- Promise.resolve()
- Promise.reject()
- Promise.all()
- Promise.race()
静态方法可以直接调用
eg:
let p1 = Promise.let flag = true('成功')
console.log(p1)
p1.then(res => {
console.log(res)
})
let p2 = Promise.reject('失败')
p2.catch(err => {
console.log(err)
})
打印结果:

Promise.resolve()/Promise.reject()使用示例
有时没有通过new得到一个Promise实例,但是也想使用.then() .catch()方法,可以使用Promise.resolve() 或者 Promise.reject() 得到一个 Promise 对象
eg:
function foo(flag) {
if(flag) {
return new Promise(resolve => {
resolve('success')
})
} else {
// return 'fail'
return Promise.reject('fail')
}
}
// let flag = true
let flag = false
foo(flag).then(res => {
console.log(res)
}, err => {
console.log(err)
})
Promise.all()/Promise.race()使用示例
Promise.all()/Promise.race()的括号里面需要放一个数组,数组中每个元素需为Promise对象
eg:
let p1 = new Promise((resolve, reject) => {
// setTimeout模拟异步操作
setTimeout(() => {
console.log(1)
resolve('1成功')
}, 1000)
})
let p2 = new Promise((resolve, reject) => {
setTimeout(() => {
console.log(2)
resolve('2成功')
// reject('2失败')
}, 2000)
})
let p3 = new Promise((resolve, reject) => {
setTimeout(() => {
console.log(3)
resolve('3成功')
}, 3000)
})
Promise.all([p1, p2, p3]).then(res => {
console.log(res)
}, err => {
console.log(err)
})
all中的所有Promise示例都会被执行,全部执行成功后,会执行then()里面的res成功状态方法
只要有一个失败,就会执行失败状态方法
全部成功打印结果:

有失败的打印结果:

Promise.all()/Promise.race()应用场景举例:图片上传,图片加载
图片一般是一张一张的上传,当全部上传成功时,提示图片上传成功
Promise.all()应用于图片上传- - -
伪代码:
const imgArr = ['1.jpg', '2.jpg', '3.jpg']
let promiseArr = []
imgArr.forEach(item => {
promiseArr.push(new Promise((resolve, reject) => {
// 图片上传操作
resolve()
}))
})
Promise.all(promiseArr).then(res => {
console.log('图片全部上传成功')
})
Promise.race()应用于图片上传- - -
要么加载成功,要么加载超时:
function getImg() {
return new Promise((resolve, reject) => {
let img = new Image()
img.onload = function() {
resolve(img)
}
img.src = 'xx.jpg'
// img.src = 'https://www.baidu.com/img/flexible/logo/pc/result@2.png'
})
}
function timeout() {
return new Promise((_resolve, reject) => {
setTimeout(() => {
reject('图片请求超时')
}, 2000)
})
}
Promise.race([getImg(), timeout()]).then(res => {
console.log(res)
}).catch(err => {
console.log(err)
})
加载超时:

加载成功:

本文探讨了回调地狱问题在JavaScript中的困扰,并介绍了如何通过Promise进行异步编程,实现代码的扁平化,降低耦合度。通过实例演示了Promise的使用和常见方法如`.then()`和`.catch()`,以及静态方法`Promise.resolve()`和`Promise.reject()`。
207

被折叠的 条评论
为什么被折叠?



