一、ES6之前异步请求的处理方式
Promise期约或者称承诺一直是面试的高频考点,非常重要,也是ES6非常重要的一个新特性,那么为什么会有期约呢。当我们调用异步函数时,是没有办法直接拿到返回结果的,因为是异步的。所以需要使用回调函数,成功时回调请求成功的函数,失败时回调请求失败的函数。但是这样非常麻烦,所以为了避免这些弊端,推出了Promise,规范好了所有代码的编写逻辑。
// 模拟网络请求
function requestData(url,sucesscallback,losemessage){
setTimeout(()=>{
if(url==="coderwhy"){
sucesscallback()
}
else{
losemessage()
}
// 该函数异步,是不可以return的,
},3000)
}
// main.js
requestData("coderwhy",(res)=>{
console.log("请求成功")
},(err)=>{
console.log("请求失败")
})
弊端:
1> 如果是我们自己封装的requestData,那么我们在封装的时候必须要自己设计好callback名称, 并且使用好。
2> 如果我们使用的是别人封装的requestData或者一些第三方库, 那么我们必须去看别人的源码或者文档, 才知道它这个函数需要怎么去获取到结果
二、Promise的基本使用--实现一个基础的异步请求
如下代码所示,模拟一个异步请求,当url传入,异步请求的代码会被放入excutor中,excutor拿到url,开始运行,如果结果是正确,则请求成功,回调promise.then中成功的函数,如果结果是非正确,则请求失败,回调promise.then中失败的函数,即第二个函数,或者是promise,catch()。
// request.js
function requestData(url,) {
// 异步请求的代码会被放入到executor中
return new Promise((resolve, reject) => {
// 模拟网络请求
setTimeout(() => {
// 拿到请求的结果
// url传入的是coderwhy, 请求成功
if (url === "coderwhy") {
// 成功
let names = ["abc", "cba", "nba"]
resolve(names)
} else { // 否则请求失败
// 失败
let errMessage = "请求失败, url错误"
reject(errMessage)
}
}, 3000);
})
}
// main.js
const promise = requestData("coderwhy")
promise.then((res) => {
console.log("请求成功:", res)
}, (err) => {
console.log("请求失败:", err)
})
// 传入的这个函数, 被称之为 executor
// > resolve: 回调函数, 在成功时, 回调resolve函数
// >reject: 回调函数, 在失败时, 回调reject函数
const promise = new Promise((resolve,rejected)=>{
// 异步请求的代码会被放入exeutor中
rejected("errmessage")//这里的参数会作为then中成功的回调函数的参数传过去
})
// then方法传入的回调函数两个回调函数:
// > 第一个回调函数, 会在Promise执行resolve函数时, 被回调
// > 第二个回调函数, 会在Promise执行reject函数时, 被回调
promise.then((res)=>{
console.log("请求成功:"+res)//res=sucess
},(err)=>{
console.log("请求失败:"+err)
})
三、Promise的三种状态
// 注意: Promise状态一旦确定下来, 那么就是不可更改的(锁定)
new Promise((resolve, reject) => {
// pending状态: 待定/悬而未决的
console.log("--------")
reject() // 处于rejected状态(已拒绝状态)
resolve() // 处于fulfilled状态(已敲定/兑现状态)
console.log("++++++++++++")
}).then(res => {
console.log("res:", res)
}, err => {
console.log("err:", err)
})
四、promise的resolve参数
const promise = new Promise((resolve,rejected)=>{
resolve( new Promise((resolve,rejected)=>{
resolve("aaaaa")
}))//这里的参数会作为then中成功的回调函数的参数传过去
// resolve(参数)
// * 1> 普通的值或者对象 pending -> fulfilled
// * 2> 传入一个Promise
// * 那么当前的Promise的状态会由传入的Promise来决定
// * 相当于状态进行了移交
})
// * 3> 传入一个对象, 并且这个对象有实现then方法(并且这个对象是实现了thenable接口)
// * 那么也会执行该then方法, 并且又该then方法决定后续状态
new Promise((resolve, reject) => {
pending -> fulfilled
const obj = {
then: function(resolve, reject) {
// resolve("resolve message")
reject("reject message")
}
}
resolve(obj)
}).then(res => {
console.log("res:", res)
}, err => {
console.log("err:", err)
})
五、Promise对象方法-then方法。
then方法是Promise对象上的一个方法:它其实是放在Promise的原型上的 Promise.prototype.then
// 1.then方法传入的回调函数两个回调函数:
// > 第一个回调函数, 会在Promise执行resolve函数时, 被回调
// > 第二个回调函数, 会在Promise执行reject函数时, 被回调
promise.then((res)=>{
console.log("请求成功:"+res)//res=sucess
},(err)=>{
console.log("请求失败:"+err)
})
// 2.then方法可以被多次调用
promise.then((res)=>{
console.log("res2:",res)
})
promise.then((res)=>{
console.log("res3:",res)
})
// 3.then方法可以被链式调用promise.then().then().then()
promise.then((res)=>{
return "11111"//会返回一个新的promise,相当于返回的是resolve("11111") 没有写返回值,相当于return:undefined
//不管返回的是普通值,还是对象还是promise,都相当于返回了一个new promise(),由这个promise的状态决定后面一个then的回调状态.
}).then(res=>{
console.log("res3:",res)
})
// 4.then方法可以后面紧跟catch方法.
promise.then(res => {
return new Promise((resolve, reject) => {
reject("then rejected status")
})
// throw new Error("error message")
}).catch(err => {
console.log("err:", err)//内部在实现时,实际上在执行时catch传入的是第一个promise的异常捕获.
// 如果第一个promise没有异常抛出,则catch会传入前面的返回的promise的异常.
})
六、Promise的catch方法
// 1.当executor抛出异常时, 也是会调用错误(拒绝)捕获的回调函数的
promise.then(undefined, err => {
console.log("err:", err)
console.log("----------")
})
// 2.通过catch方法来传入错误(拒绝)捕获的回调函数
// promise/a+规范
promise.catch(err => {
console.log("err:", err)
})
promise.then(res => {
return new Promise((resolve, reject) => {
reject("then rejected status")
})
throw new Error("error message")
}).catch(err => {
console.log("err:", err)//内部在实现时,实际上在执行时catch传入的是第一个promise的异常捕获.
})
// 3.catch方法的返回值
const promise = new Promise((resolve, reject) => {
reject("111111")
})
promise.then(res => {
console.log("res:", res)
}).catch(err => {
console.log("err:", err)
return "catch return value"//catch里面也是返回一个新的promise,除非抛出异常会调用后面的catch,否则还是调用后面的then方法.
}).then(res => {
console.log("res result:", res)
}).catch(err => {
console.log("err result:", err)
})
七、promise的对象方法-finaly
const promise = new Promise((resolve, reject) => {
// resolve("resolve message")
reject("reject message")
})
promise.then(res => {
console.log("res:", res)
}).catch(err => {
console.log("err:", err)
}).finally(() => {
console.log("finally code execute")
// 无论promise捕获的异常还是非异常,都会执行finally的代码
})
八、promise中的类方法promise.resolve
/ 类方法Promise.resolve
// 1.普通的值
const promise = Promise.resolve({ name: "why" })
相当于
const promise2 = new Promise((resolve, reject) => {
resolve({ name: "why" })
})
// 2.传入Promise
const promise = Promise.resolve(new Promise((resolve, reject) => {
resolve("11111")
}))
promise.then(res => {
console.log("res:", res)
})
// 3.传入thenable对象
/ 类方法Promise.resolve
// 1.普通的值
const promise = Promise.resolve({ name: "why" })
相当于
const promise2 = new Promise((resolve, reject) => {
resolve({ name: "why" })
})
// 2.传入Promise
const promise = Promise.resolve(new Promise((resolve, reject) => {
resolve("11111")
}))
promise.then(res => {
console.log("res:", res)
})
// 3.传入thenable对象
九、promise中的类方法promise.rejected()
/ const promise = Promise.reject("rejected message")
// 相当于
// const promise2 = new Promsie((resolve, reject) => {
// reject("rejected message")
// })
// 注意: 无论传入什么值都是一样的
const promise = Promise.reject(new Promise(() => {}))
// 传入promise,直接打印err:promise{pending}
// 传入function,直接返回then:[function:then]
promise.then(res => {
console.log("res:", res)
}).catch(err => {
console.log("err:", err)
})
十、promise中的类方法promise.all()
const p1 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve(11111)
}, 1000);
})
const p2 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve(22222)
}, 2000);
})
const p3 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve(33333)
}, 3000);
})
// 需求: 所有的Promise都变成fulfilled时, 再拿到结果
// 意外: 在拿到所有结果之前, 有一个promise变成了rejected, 那么整个promise是rejected
Promise.all([p2, p1, p3, "aaaa"]).then(res => {
//按照存放在数组的顺序输出,与执行的顺序无关。
//全部都是fullilled,会输出所有的执行结果,如果有一个是rejected,then不会执行,只会执行catch,只会返回rejected的结果.(这也是一个弊端。)
console.log(res)
}).catch(err => {
console.log("err:", err)
})
十一、promise类方法-allsetted()
const p1 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve(11111)
}, 1000);
})
const p2 = new Promise((resolve, reject) => {
setTimeout(() => {
reject(22222)
}, 2000);
})
const p3 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve(33333)
}, 3000);
})
// allSettled
Promise.allSettled([p1, p2, p3]).then(res => {
console.log(res)
}).catch(err => {
console.log(err)
})
结果以数组方式呈现:
[{status: 'fulfilled', value: 11111}
{status: "rejected", reason: 22222}
{status: 'fulfilled', value: 33333}]
十二、promise的类方法-race()
const p1 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve(11111)
}, 3000);
})
const p2 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve(22222)
}, 500);
})
const p3 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve(33333)
}, 1000);
})
// race: 竞技/竞赛
// 只要有一个Promise变成fulfilled状态, 那么就结束
// 意外:
Promise.race([p1, p2, p3]).then(res => {
console.log("res:", res)//以上代码输出结果为res:22222。
}).catch(err => {
console.log("err:", err)
})
十三、promise的类方法-any()
const p1 = new Promise((resolve, reject) => {
setTimeout(() => {
// resolve(11111)
reject(1111)
}, 1000);
})
const p2 = new Promise((resolve, reject) => {
setTimeout(() => {
reject(22222)
}, 500);
})
const p3 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve(33333)
// reject(3333)
}, 3000);
})
// any方法
//至少等到一个resolve,执行then.如果没有resolve,等到所有rejected的执行完毕,全部返回,抛出一个合并的异常。
Promise.any([p1, p2, p3]).then(res => {
console.log("res:", res)
}).catch(err => {
console.log("err:", err.errors)
})
好了,以上就是promise的基本使用方法啦,xia一节,我们开始手写promise。