1 异步代码的困境
2 认识Promise作用
3 Promise基本使用
4 Promise状态变化
5 Promise实例方法
6 Promise的类方法
找以前的异步代码都是通过以下的方式封装的,有个缺点就是每个人写的execCode的参数顺序不一样,使用者可能会出现报错什么的,而且主要写的东西也是非常多。
// 1.设计这样的一个函数 function execCode(counter, successCallback, failureCallback) { // 异步任务 setTimeout(() => { if (counter > 0) { // counter可以计算的情况 let total = 0 for (let i = 0; i < counter; i++) { total += i } // 在某一个时刻只需要回调传入的函数 successCallback(total) } else { // 失败情况, counter有问题 failureCallback(`${counter}值有问题`) } }, 3000) } // 2.ES5之前,处理异步的代码都是这样封装 execCode(100, (value) => { console.log("本次执行成功了:", value) }, (err) => { console.log("本次执行失败了:", err) })
1
function execCode(counter) { const promise = new Promise((resolve, reject) => { // 异步任务 setTimeout(() => { if (counter > 0) { // counter可以计算的情况 let total = 0 for (let i = 0; i < counter; i++) { total += i } // 成功的回调 resolve(total) } else { // 失败情况, counter有问题 // 失败的回调 reject(`${counter}有问题`) } }, 3000) }) return promise } // const promise = execCode(100) // promise.then((value) => { // console.log("成功有了结果: ", value) // }) // promise.catch((err) => { // console.log("失败有了错误: ", err) // }) // const promise2 = execCode(-100) // promise2.then(value => { // console.log("成功:", value) // }) // promise2.catch(err => { // console.log("失败:", err) // }) // 执行一次 execCode(255).then(value => { console.log("成功:", value) }).catch(err => { console.log("失败:", err) })
1
// 1.创建一个Promise对象 const promise = new Promise((resolve, reject) => { // 注意: Promise的状态一旦被确定下来, 就不会再更改, 也不能再执行某一个回调函数来改变状态 // 1.待定状态 pending console.log("111111") console.log("222222") console.log("333333") // 2.兑现状态 fulfilled resolve() // 3.拒绝状态 rejected reject() }) promise.then(value => { console.log("成功的回调") }).catch(err => { console.log("失败的回调") }) // executor const promise2 = new Promise((resolve, reject) => { })
1
const p = new Promise((resolve) => { // setTimeout(resolve, 2000) setTimeout(() => { resolve("p的resolve") }, 2000) }) const promise = new Promise((resolve, reject) => { // 1.普通值 // resolve([ // {name: "macbook", price: 9998, intro: "有点贵"}, // {name: "iPhone", price: 9.9, intro: "有点便宜"}, // ]) // 2.resolve(promise) // 如果resolve的值本身Promise对象, 那么当前的Promise的状态会有传入的Promise来决定 // resolve(p) // 3.resolve(thenable对象) resolve({ name: "kobe", then: function(resolve) { resolve(11111) } }) }) promise.then(res => { console.log("then中拿到结果:", res) })
1
const promise = new Promise((resolve, reject) => { resolve("success") // reject("failure") }) // promise.then(res => { // }).catch(err => { // }) // 1.then参数的传递方法: 可以传递两个参数 // 这种写法也是可以的 // promise.then(res => { // console.log("成功回调~", res) // }, err => { // console.log("失败回调~", err) // }) promise.then(res => { console.log("成功回调~", res) }) promise.then(res => { console.log("成功回调~", res) }) promise.then(res => { console.log("成功回调~", res) }) promise.then(res => { console.log("成功回调~", res) })
1
const promise = new Promise((resolve, reject) => { reject("failure") }) promise.then(res => { console.log("成功的回调:", res) }).catch(err => { console.log("失败的回调:", err) }) promise.catch(err => { console.log("失败的回调:", err) }) promise.catch(err => { console.log("失败的回调:", err) }) promise.catch(err => { console.log("失败的回调:", err) }) promise.catch(err => { console.log("失败的回调:", err) })
then的返回值是新的promise,连续的.then是上一个then的返回值,不同于promise的调度方法
const promise = new Promise((resolve, reject) => { resolve("aaaaaaa") // reject() }) // 1.then方法是返回一个新的Promise, 这个新Promise的决议是等到then方法传入的回调函数有返回值时, 进行决议 // Promise本身就是支持链式调用 // then方法是返回一个新的Promise, 链式中的then是在等待这个新的Promise有决议之后执行的 // promise.then(res => { // console.log("第一个then方法:", res) // return "bbbbbbbb" // }).then(res => { // console.log("第二个then方法:", res) // return "cccccccc" // }).then(res => { // console.log("第三个then方法:", res) // }) // promise.then(res => { // console.log("添加第二个then方法:", res) // }) // 2.then方法传入回调函数的返回值类型 const newPromise = new Promise((resolve, reject) => { setTimeout(() => { resolve("why") }, 3000) }) promise.then(res => { console.log("第一个Promise的then方法:", res) // 1.普通值 // return "bbbbbbb" // 2.新的Promise // return newPromise // 3.thenable的对象 return { then: function(resolve) { resolve("thenable") } } }).then(res => { console.log("第二个Promise的then方法:", res) // undefined })
catch后面返回的也是promise,也可以通过then拿到返回值。
只要promise先决议的是resolve,不管有多少个then,then全部都执行,catch不会执行;
只要promise先决议reject,不管catch前面有多少个then都不会执行,就马上执行catch里面的内容。
可以通过抛出异常来进入catch,如果抛出异常后没有catch会报错。
const promise = new Promise((resolve, reject) => { // reject("error: aaaaa") resolve("aaaaaa") }) // 1.catch方法也会返回一个新的Promise // promise.catch(err => { // console.log("catch回调:", err) // return "bbbbb" // }).then(res => { // console.log("then第一个回调:", res) // return "ccccc" // }).then(res => { // console.log("then第二个回调:", res) // }) // 2.catch方法的执行时机 promise.then(res => { console.log("then第一次回调:", res) // throw new Error("第二个Promise的异常error") return "bbbbbb" }).then(res => { console.log("then第二次回调:", res) throw new Error("第三个Promise的异常error") }).then(res => { console.log("then第三次回调:", res) }).catch(err => { console.log("catch回调被执行:", err) }) // 中断函数继续执行: // 方式一: return // 方式二: throw new Error() // 方式三: yield 暂停(暂时性的中断)
兜底方法,执行过then或者catch之后一定会执行的方法。
const promise = new Promise((resolve, reject) => { // pending // fulfilled resolve("aaaa") // rejected // reject("bbbb") }) promise.then(res => { console.log("then:", res) // foo() }).catch(err => { console.log("catch:", err) // foo() }).finally(() => { console.log("哈哈哈哈") console.log("呵呵呵呵") }) function foo() { console.log("哈哈哈哈") console.log("呵呵呵呵") }
实例方法是不要要创建实例对象才能使用的,new xxx的实例对象。
类方法是单独类名.xxx方法就能直接使用。
如果单纯需要拿个异步的某个参数,可以直接写类方法来简化代码。
// 实例方法 // const promise = new Promise((resolve) => { // // 进行一系列的操作 // resolve("result") // }) // promise.catch // 类方法 const studentList = [] const promise = Promise.resolve(studentList) promise.then(res => { console.log("then结果:", res) }) // 相当于 // new Promise((resolve) => { // resolve("Hello World") // })
1
// 类方法 const promise = Promise.reject("rejected error") promise.catch(err => { console.log("err:", err) }) // 相当于 _表示resolve,这个位置一定不能变,因为promise就是2个参数,不要少写 // new Promise((_, reject) => { // reject("rejected error") // })
需要等待前面多个promise都执行resolve完成之后在执行某个then的话使用all的then。同理如果all里面某个promise返回了reject的话,那all的then就执行不了了,会跳到all的catch
里面去执行。
// 创建三个Promise const p1 = new Promise((resolve, reject) => { setTimeout(() => { // resolve("p1 resolve") reject("p1 reject error") }, 3000) }) const p2 = new Promise((resolve, reject) => { setTimeout(() => { resolve("p2 resolve") }, 2000) }) const p3 = new Promise((resolve, reject) => { setTimeout(() => { resolve("p3 resolve") }, 5000) }) // all:全部/所有 Promise.all([p1, p2, p3]).then(res => { console.log("all promise res:", res) }).catch(err => { console.log("all promise err:", err) })
这个是all方法的强化班,一定会执行then。会返回每个promise 的状态。
// 创建三个Promise const p1 = new Promise((resolve, reject) => { setTimeout(() => { // resolve("p1 resolve") reject("p1 reject error") }, 3000) }) const p2 = new Promise((resolve, reject) => { setTimeout(() => { resolve("p2 resolve") }, 2000) }) const p3 = new Promise((resolve, reject) => { setTimeout(() => { resolve("p3 resolve") }, 5000) }) // 类方法: allSettled Promise.allSettled([p1, p2, p3]).then(res => { console.log("all settled:", res) })
拿来测试代码速度的一个办法,就是有多个promise的情况下,哪个执行快就then哪个出来。
缺点是不管是resolve还是reject先输出,都会看成是完成了。
// 创建三个Promise const p1 = new Promise((resolve, reject) => { setTimeout(() => { resolve("p1 resolve") // reject("p1 reject error") }, 3000) }) const p2 = new Promise((resolve, reject) => { setTimeout(() => { // resolve("p2 resolve") reject("p2 reject error") }, 2000) }) const p3 = new Promise((resolve, reject) => { setTimeout(() => { resolve("p3 resolve") }, 5000) }) // 类方法: race方法 // 特点: 会等到一个Promise有结果(无论这个结果是fulfilled还是rejected) Promise.race([p1, p2, p3]).then(res => { console.log("race promise:", res) }).catch(err => { console.log("race promise err:", err) })
是race的优化版,只会将最先完成的resolve的结果输出
// 创建三个Promise const p1 = new Promise((resolve, reject) => { setTimeout(() => { // resolve("p1 resolve") reject("p1 reject error") }, 3000) }) const p2 = new Promise((resolve, reject) => { setTimeout(() => { // resolve("p2 resolve") reject("p2 reject error") }, 2000) }) const p3 = new Promise((resolve, reject) => { setTimeout(() => { // resolve("p3 resolve") reject("p3 reject error") }, 5000) }) // 类方法: any方法 Promise.any([p1, p2, p3]).then(res => { console.log("any promise res:", res) }).catch(err => { console.log("any promise err:", err) })