# subject1-promise **Repository Path**: javascript-knowage/subject1-promise ## Basic Information - **Project Name**: subject1-promise - **Description**: Promise从入门到手写 - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2024-02-22 - **Last Updated**: 2024-02-22 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README ## Promise入门到手写 ### 入门: #### 01 状态改变: Promise对象的状态分为三种:pending、fulfilled和rejected。 状态改变只能是pending到fulfilled或者是pending到rejected。 ```javascript const p1 = new Promise((resolve, reject) => { }) const p2 = new Promise((resolve, reject) => { resolve("success") }) const p3 = new Promise((resolve, reject) => { reject("error") }) console.log(p1); // Promise {} console.log(p2); // Promise {: 'success'} console.log(p3); // Promise {: 'error'} ``` #### 02 实例方法then: then方法用于得到成功value的成功回调和用于得到失败reason的失败的回调,**并且将返回一个新的Promise实例化对象。** - 成功状态:执行then方法的第一个回调函数 - 失败状态:执行then方法的第二个回调函数 ```javascript const p0 = new Promise((resolve, reject) => { setTimeout(() => { resolve("成功") }, 2000) }) p0.then(value => { console.log(value) // 成功 }, error => { console.log(error) }) ``` then方法的返回值也是一个Promise对象,该返回值对象的状态取决于回调函数中的内容: - 如果返回为非Promise实例化对象,则得到是一个成功的Promise。 - 如果返回为Promise实例化对象,则该实例化对象的状态和结果直接影响后续then方法链式调用的状态和结果。 ```javascript // 返回非Promise对象,得到的是一个成功的Promise const p0 = new Promise((resolve, reject) => { resolve("p0") }) const p1 = p0.then(value => { return `${value} => p1`; }) p1.then(res => { console.log(res) // p0 => p1 }) // 返回Promise对象,则该返回值状态和结果直接影响后续then方法链式调用的状态和结果 const p0 = new Promise((resolve, reject) => { resolve("p0") }) const p1 = p0.then(value => { return new Promise((resolve, reject) => { reject(`error: ${value} => p1`) }) }) p1.then(value => { console.log(value) }, reason => { console.log(reason); // error: p0 => p1 }) ``` #### 03 静态方法all: Promise下的静态方法all主要是针对于多个Promise的异步任务的处理。 需要接收一个数组类型的形参,返回值也是一个Promise对象,只有数组中的Promise对象状态都是成功的,最终才会返回成功的状态,并且将每个Promise对象的返回值包装成一个数组。 ```javascript const p1 = new Promise((resolve, reject) => { setTimeout(() => { resolve(new Date().getTime()) }, 1000) }) const p2 = new Promise((resolve, reject) => { setTimeout(() => { resolve(new Date().getTime()) }, 2000) }) const p3 = new Promise((resolve, reject) => { setTimeout(() => { resolve(new Date().getTime()) }, 3000) }) const P = Promise.all([p1, p2, p3]) P.then(res => { console.log(res) }) ``` #### 04 静态方法allSettled: all方法要求所有的Promise对象都返回成功状态时才会触发成功状态,如果有任何一个Promise对象触发reject,则all方法返回的就是reject状态。 allSettled则是所有Promise对象都返回结果时触发,返回的结果数组中包含对应Promise对象的结果status值。 ```javascript const p1 = new Promise((resolve, reject) => { setTimeout(() => { resolve(new Date().getTime()) }, 1000) }) const p2 = new Promise((resolve, reject) => { setTimeout(() => { resolve(new Date().getTime()) }, 2000) }) const p3 = new Promise((resolve, reject) => { setTimeout(() => { reject("error: " + new Date().getTime()) }, 3000) }) const P = Promise.allSettled([p1, p2, p3]) P.then(res => { console.log(res) // }, reason => { console.log(reason) }) // 成功的项目:{status: 'fulfilled', value: 1704438511694} // 失败的项目:{status: 'rejected', reason: 'error: 1704438513692'} ``` #### 05 静态方法any: any方法也是接收一个Promise对象组成的数组,只要数组中的Promise对象有一个状态为fulfilled,则整体结果就会是fulfilled。 如果所有的Promise对象实例都是rejected,那么结果就是rejected。 ```javascript const p1 = new Promise((resolve, reject) => { setTimeout(() => { reject("p1 => " + new Date().getTime()) }, 1000) }) const p2 = new Promise((resolve, reject) => { setTimeout(() => { reject("p2 => " + new Date().getTime()) }, 2000) }) const p3 = new Promise((resolve, reject) => { setTimeout(() => { reject("p3 => " + new Date().getTime()) }, 3000) }) const P = Promise.any([p1, p2, p3]) P.then(res => { console.log(res) }, reason => { console.log(reason) // AggregateError: All promises were rejected }) ``` #### 06 静态方法race: race方法接收一个Promise对象组成的数组,该数组中任意一个Promise对象状态发送了改变就会返回。 race方法总是返回参数数组中状态改变最快的那个Promise对象的返回值。 ```javascript const p1 = new Promise((resolve, reject) => { setTimeout(() => { resolve("p1 => " + new Date().getTime()) }, 1000) }) const p2 = new Promise((resolve, reject) => { setTimeout(() => { reject("p2 => " + new Date().getTime()) }, 2000) }) const p3 = new Promise((resolve, reject) => { setTimeout(() => { reject("p3 => " + new Date().getTime()) }, 3000) }) const P = Promise.race([p1, p2, p3]) P.then(res => { console.log("success: " + res) // success: p1 => 1704440053827 }, reason => { console.log("error: " + reason) }) ``` #### 07 静态方法reject: 静态方法reject返回一个状态为rejected的Promise对象。 ```javascript const p1 = Promise.reject("失败的原因"); p1.catch(reason => { console.log(reason) }) ``` #### 08 静态方法resolve: 静态方法resolve会将一个普通的值转换成Promise类型的数据。 它和then相似,resolve中的参数决定着返回状态和返回结果。 ```javascript const p1 = Promise.resolve("成功"); p1.then(value => { console.log(value) // 直接打印 “成功” }) const p2 = Promise.resolve(new Promise((resolve, reject) => { setTimeout(() => { resolve("p2 success") }, 2000) })) p2.then(value => { console.log(value) // 两秒后打印 "p2 success" }) ``` #### 09 实例方法catch: 在Promise对象上可以使用catch方法来捕获异常。 catch方法也是可以有返回值的,不同的返回值对应不同的处理方式: - catch回调函数中没有返回值,则返回一个成功的Promise对象,结果为undefined - catch回调函数中有返回值,该返回值为普通数据,则得到一个成功的Promise对象,结果为该返回值。 - catch回调函数中返回一个Promise对象,新的Promise对象的状态和结果完全取决于返回的Promise对象的状态和结果。 ```javascript const p = new Promise((resolve, reject) => { reject("rejected的原因") }) // catch返回的也是一个Promise对象 const c = p.catch(reason => { console.log(reason) }) // 没有返回值时则是返回一个成功的Promise,状态返回值为undefined c.then(value => { console.log(value) }) ``` > 异常穿透:catch方法捕获最终生成的失败回调,中间有可能隔着几个then函数的调用,这种特性简称异常穿透。 #### 10 实例方法finally: finally是ES9中新增的特性,表示无论Promise对象变成fulfilled还是rejected状态,最终都会执行。 ```javascript const p = new Promise((resolve, reject) => { setTimeout(() => { reject("rejected") }, 2000) }) p.then(value => { console.log(value) }, reason => { console.log(reason) }).finally(() => { console.log("finally") }) ``` #### 11 Promise链条的中止: Promise链条的中止其实就是在then函数中返回一个pending状态的Promise实例。 ```javascript const p = new Promise((resolve, reject) => { resolve("fulfilled") }) p.then(value => { console.log('0=> ' + value) }).then(value => { console.log('1=> ' + value) // 返回一个pending状态的Promise对象,中止了then函数的链式调用 return new Promise((resolve, reject) => {}) }).then(value => { console.log('2=> ' + value) }).finally(() => { console.log("end=> finally") }) ``` #### 12 async函数: async函数返回一个Promise对象,返回值可以是以下三种: - 直接返回值:包装成resolve的Promise对象。 - Promise对象返回值: - 抛出异常: ```javascript async function getData1() { return "getData1" } async function getData2() { return new Promise((resolve, reject) => { resolve("getData2 fulfilled") }) } async function getData3() { throw new Error("报错了") } const res1 = getData1(); const res2 = getData2(); const res3 = getData3(); res1.then(value => { console.log("res1: " + value); // res1: getData1 }) res2.then(value => { console.log("res2: " + value); // res2: getData2 fulfilled }) res3.catch(err => { console.log("res3: " + err); // res3: Error: 报错了 }) ``` #### 13 await表达式: await表达式一定要结合async函数,await相当于then,可以直接拿到成功的Promise实例对象的结果值。 ```javascript async function getData() { const res = await Promise.resolve("fulfilled value"); console.log(res) } getData(); ``` await表达式只能接收成功的Promise实例对象结果值,如果不但接收成功的结果值还是失败的结果值,那就必须使用try catch。 ```javascript async function getList() { try { const res = await Promise.reject("rejected value") } catch (error) { console.log(error) } } getList(); ``` ### 手写: #### 01 基本结构: Promise是一个构造函数,作用就是为了实例化对象。 Promise构造函数需要接收一个实际参数,类型为一个函数(执行器函数executor) executor回调函数中也是需要接收两个参数:resolve和reject。 ```javascript // 1、Promise是一个构造函数,作用就是为了实例化对象 // 2、Promise需要接收一个实际参数,类型是一个回调函数 (function (window) { function Promise(executor) { executor(); } window.Promise = Promise; })(window); ``` #### 02 实例属性: 每一个Promise对象都有两个固定的属性值:PromiseState和PromiseResult,前者记录Promise对象的状态,后者记录Promise对象的返回值。 ```javascript (function (window) { function Promise(executor) { this.PromiseState = "pending"; this.PromiseResult = undefined; executor(); } window.Promise = Promise; })(window); ``` #### 03 状态改变: Promise对象中的状态改变是通过resolve函数和reject函数进行操作的: - 调用resolve方法,可以将Promise实例化对象的状态从pending→fulfilled; - 调用reject方法,可以将Promise实例化对象的状态从pending→rejected; - Promise实例化对象状态一旦被更改,则不会再继续发生更改; - 抛出异常的情况下,Promise实例化对象会将异常捕获,状态改为rejected。 ```javascript (function (window) { function Promise(executor) { this.PromiseState = "pending"; this.PromiseResult = undefined; // resolve方法 var resolve = function (result) { if (this.PromiseState === "pending") { this.PromiseState = "fulfilled"; this.PromiseResult = result; } }.bind(this); // reject方法 var reject = function (result) { if (this.PromiseState === "pending") { this.PromiseState = "rejected"; this.PromiseResult = result; } }.bind(this); // 捕获异常,异常状态下是rejected try { executor(resolve, reject); } catch (error) { this.PromiseState = "rejected"; error.message ? this.PromiseResult = error.message : this.PromiseResult = error; } } window.Promise = Promise; })(window); ``` #### 04 then函数基础实现: then方法需要传递两个回调函数,onfulfilled和onrejected,在Promise实例对象状态改变为fulfilled时调用onfulfilled函数,反之调用onrejected函数。 ```javascript (function (window) { function Promise(executor) { this.PromiseState = "pending"; this.PromiseResult = undefined; // resolve方法 var resolve = function (result) { if (this.PromiseState === "pending") { this.PromiseState = "fulfilled"; this.PromiseResult = result; } }.bind(this); // reject方法 var reject = function (result) { if (this.PromiseState === "pending") { this.PromiseState = "rejected"; this.PromiseResult = result; } }.bind(this); // 捕获异常,异常状态下是rejected try { executor(resolve, reject); } catch (error) { this.PromiseState = "rejected"; error.message ? (this.PromiseResult = error.message) : (this.PromiseResult = error); } } // then函数 Promise.prototype.then = function (onfulfilled, onrejected) { if (this.PromiseState === "fulfilled") { onfulfilled(this.PromiseResult); } if (this.PromiseState === "rejected") { onrejected(this.PromiseResult); } }; window.Promise = Promise; })(window); ``` #### 05 then函数是异步调用的: then方法时异步方法,在监测到实例对象状态发生改变时,不会立即执行,只有所有的同步方法执行完毕后才会执行onfulfilled或者onrejected。 ```javascript (function (window) { // 构造函数 function Promise(executor) { this.PromiseState = "pending"; this.PromiseResult = undefined; // resolve方法 var resolve = function (value) { if (this.PromiseState === "pending") { this.PromiseResult = value; this.PromiseState = "fulfilled"; } }.bind(this); // reject方法 var reject = function (reason) { if (this.PromiseState === "pending") { this.PromiseResult = reason; this.PromiseState = "rejected"; } }.bind(this); // 捕获异常,异常状态下是rejected try { executor(resolve, reject); } catch (error) { this.PromiseState = "rejected"; error.message ? (this.PromiseResult = error.message) : (this.PromiseResult = error); } } // 实例方法 Promise.prototype.then = function (onfulfilled, onrejected) { if (this.PromiseState === "fulfilled") { // then方法中的回调方法是异步的 setTimeout( function () { onfulfilled(this.PromiseResult); }.bind(this) ); } if (this.PromiseState === "rejected") { setTimeout( function () { onrejected(this.PromiseResult); }.bind(this) ); } }; window.Promise = Promise; })(window); ```