1.什么是Promise
Promise是异步编程的一种解决方案, 比传统的解决方案(回调函数)更合理更强大
2.为什么要解决异步问题
1.异步回调不符合开发思想
2.代码不美观
3.回调地狱, 拿到一个数据需要一些条件
回调地狱案例:
$.ajax({
url:'http://api2.xqb.ink/api/courses',
success(res){
console.log( res,'列表内容' )
let id = res.result[0].course_id
$.ajax({
url:'http://api2.xqb.ink/api/course',
data:{
id
},
success(res){
console.log(res,'详情内容')
}
})
}
})
3.为什么Promise更强大?
promise是一个容器, 里面保存着某个未来才会结束的事件的结果
promise是一个对象, 它提供统一的方法, 去处理各种异步操作
Promise的三种状态
- pending 进行中
- fullfilled 已成功
- rejected 已失败
Promise的特点
- Promise对象不受外界影响, 只有异步操作的结果可以决定当前是哪种状态
- 一旦状态改变, 就不会再变, 会一直保持这个结果, 这个时候称为resolved
- Promise的状态只有两种可能: pending - fulfilled pending - rejected
- Promise它本身不是异步的, 它是解决异步的
- Promise实例化的时候需要传一个回调函数, 回调函数内部处理异步事件
- Promise实例化, 这个函数会立刻执行, 并且接收2个参数: resolve解决完成 reject失败
- Promise实例化后, 会返回一个promise对象, 这个对象里面有then方法和catch方法
- then接收成功的结果
- catch捕获错误
4.代码实例
// resolve() 结果成功需要调用的函数
// reject() 结果失败需要调用的函数
let p = new Promise(function (resolve, reject) {
// 存放着未来才有结果的一件事
// resolve("ajax接收到的数据")
reject("Fail");
})
console.log(p);
// 成功之后怎么办, then是成功之后
// p.then(function(res){
// console.log(res);
// });
// 失败之后怎么办, catch是失败之后执行的, 也就是reject()调用之后执行的函数
// catch捕捉错误
p.catch(function (err) {
console.log(err);
})
链式操作
// 链式操作
p.then(function (res) {
console.log(res);
}).catch(function (err) {
console.log(err);
})
let p = new Promise(function(resolve, reject){
resolve("SUCCESS!");
// reject("FAIL")
})
// 链式操作
p.then(); // 会返回一个promise, 可以给这个promise起一个名字小明
p.then((res)=>{
return 123 // 123是小明这个promise的resolve(123)的参数
})
p.then((res)=>{
return new Promise() //如果返回的不是普通值,而是一个promise,那么这个新的promise会代替小明
})
- 如果then的回调函数里面的返回值是普通值的时候, then调用之后会返回一个promise, 这个then的回调函数里面的返回值是这个promise的resolve参数
- 如果then的回调函数里面的返回值是一个promise的时候, 那么这个回调函数返回的promise就替代then返回的promise
Promise与Ajax封装
/* $.ajax({
url: 'http://api2.xqb.ink/api/courses',
success(res) {
console.log(res, '列表内容')
let id = res.result[0].course_id
$.ajax({
url: 'http://api2.xqb.ink/api/course',
data: { id: id },
success(res) {
console.log(res, '详情内容')
}
})
}
}) */
function PromiseAjax(url, data) {
let p = new Promise((resolve, reject) => {
$.ajax({
url,
data,
success: function (response) {
resolve(response)
},
error: function (err) {
reject(err)
}
});
})
return p;
}
PromiseAjax('http://api2.xqb.ink/api/courses').then((res) => {
console.log(res);/// 拿到一级数据
let id = res.result[0].course_id//拿到id之后,可以请求第二层数据了
return PromiseAjax("http://api2.xqb.ink/api/course", { id })
}).then((res) => {
console.log(res);
// 渲染页面
}).catch((err) => {
})
Promise与async, await
// 1.封装 ajax-promise函数
function pro({ type = "get", url, data = {}, dataType = "json" } = {}) {
// 声明promise
let p = new Promise((resolve, reject) => {
$.ajax({
type,
url,
data,
dataType,
success: function (res) {
resolve(res);
},
error: function (err) {
reject(err);
}
});
})
return p;
}
// 2.调用pro函数
/* pro({url:"http://api2.xqb.ink/api/courses"}).then((res) =>{
console.log(res, "一级数据");
let id = res.result[0].course_id;
return pro({url:"http://api2.xqb.ink/api/course",data:{ id }})
}).then((res) =>{
console.log(res, "二级数据");
}).catch((err)=>{
console.log(err);
}) */
// 3函数封装
function to(promise) {
return promise.then((res) => {
return [null, res]
}).catch((err) => {
return [err]
})
}
// async...await 只能处理正确的结果, 所以要把catch转换成then
async function run() {
let [err1, res1] = await to(pro({ url: "http://api2.xqb.ink/api/courses" }))
let id = res1.result[0].course_id;
console.log(err1, res1);
let [err2, res2] = await to(pro({ url: "http://api2.xqb.ink/api/course", data: { id } }))
console.log(err2, res2);
}
// 调用封装函数
run();