在实际的开发中,不希望这种不断嵌套的回调,而是希望将这种多层变成一层。
要解决这个回调地狱的问题,就要用到Promise对象
首先了解一下同步和异步:
(1)同步模式:
同步模式指的就是代码中的任务依次执行。后一个任务必须等待前一个任务结束后,才能执行。程序的执行顺序与我们代码的编写顺序是完全一致的。
(2)异步模式:
异步模式对应的API
是不会等待这个任务的结束才开始下一个任务,对于耗时操作,开启过后就立即往后执行下一个任务。
耗时任务的后续逻辑一般会通过回调函数的方式定义(例如ajax回调函数)
Promise 对象的基本使用
所谓的Promise就是一个对象,而Promise对象代表的是一个异步任务,也就是需要很长时间去执行的任务。
也就是通过Promise对象,可以将异步操作以同步操作的流程表达出来,避免了层层嵌套的回调函数问题,也就是回调地狱的问题。
// Promise 对象的基本使用
// Promise 有个函数参数
// 成功就执行reject函数,失败就执行reject函数
let promise = new Promise(function (resolve, reject) {
// 用定时器模拟一个异步任务
setTimeout(() => {
// 获取一个随机数,大于0.3就成功,否则失败
let num = Math.random()
if (num > 0.3) {
resolve("成功")
} else {
reject("失败")
}
}, 3000)
})
// 看Promise的执行结果就是用.then
// 里面有两个参数,成功时执行第一个回调函数
// 失败执行第二个回调函数
promise.then((value) => {
console.log(value);
}, (err) => {
console.log(err);
})
Promise 封装ajax
// Promise 封装ajax操作
let getJson = function (url) {
let p = new Promise(function (resolve, reject) {
let xhr = new XMLHttpRequest()
xhr.open("get", url)
// 如果是post请求
// xhr.open("post", url)
// xhr.setRequestHeader("Accept", "application/json")
xhr.send()
xhr.onreadystatechange = function () {
if (xhr.readyState === 4 && xhr.status === 200) {
resolve(this.response)
} else {
reject(new Error(this.statusText))
}
}
})
return p
}
getJson("http://localhost:3000/projects").then((result) => {
console.log(result);
}, (err) => {
console.log(err);
})
Promise 链式调用问题
Promise.then方法返回的也是一个Promise对象,返回一个全新的Promise对象,就是为了形成.then那个链条,完成链式调用
then方法第一个参数是成功的回调,第二个参数是失败的回调,当然第二个参数是可以省略的
如果我们不断的链式调用then
方法,然后这里每个then
方法,都是为上一个then
方法返回的Promise
对象添加状态明确后的回调
let getJson = function (url) {
let p = new Promise(function (resolve, reject) {
let xhr = new XMLHttpRequest()
xhr.open("get", url)
xhr.send()
xhr.onreadystatechange = function () {
if (xhr.readyState === 4 && xhr.status === 200) {
resolve(this.response)
} else {
reject(new Error(this.statusText))
}
}
})
return p
}
getJson("http://localhost:3005/products")
.then(function (value) {
console.log(value);
console.log("111");
return getJson("http://localhost:3005/cart");
})
// 链式回调
.then(function (value) {
console.log("then2=", value);
console.log("222");
})
Promise 处理异常的方法:
通过catch捕获异常:如果是链式回调,则把catch写在最后面,这样哪里处了问题都可以捕获到
getJson("http://localhost:3000/projects").then((result) => {
console.log(result);
}).catch((err) => {
console.log(err);
})
Promise.all()方法:等待所有任务结束后才会结束
接收一个数组,数组中每个元素都是promise,需要注意的就是all
方法中所有Promise
对象都执行成功了,才表示成功,只要有一个失败了,那么all
方法的执行就失败了。
Promise.all([promise1, promise2]).then(function(data) {
console.log(data);
})
Promise.race()方法:数组中只要有一个任务完成就结束
Promise中的静态方法:
// Promise 的静态方法
// Promise.resolve() 快速的将一个值转换成Promise对象
Promise.resolve("abc").then(function (value) {
console.log(value);
})
// Promise.reject() 创建一个失败的Promise对象
Promise.reject(new Error("失败")).catch(function (err) {
console.log(err);
})