# hand_promise **Repository Path**: one_pic/hand_promise ## Basic Information - **Project Name**: hand_promise - **Description**: 手写Promise实现 - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2022-01-20 - **Last Updated**: 2022-01-24 ## Categories & Tags **Categories**: Uncategorized **Tags**: Promise ## README # 手写Promise实现 ## 结构搭建 解决异常 TypeError: p.then is not a function 为Promise构造函数 添加原型方法 then ## 执行器函数 Promise的参数传入的是 (reslove, reject) => {} 同步调用的执行器函数 ## Promise的两个属性值 PromiseState: 状态 1. pending 初始值,等待状态 2. fulfilled 成功 3. rejected 失败 PromiseResult: 结果值 ## reslove函数 修改PromiseState pending -> fulfilled,修改PromiseResult结果 ## reject函数 修改PromiseState pending -> rejected,修改PromiseResult结果 ## 执行器函数的异常拦截 当执行器函数执行过程中抛出异常的时候,会改变PromiseState为失败状态,抛出的异常就是失败的结果值 ## PromiseState状态变化 Promise状态只能修改一次,要么成功,要么失败。只要状态变化了,就不能再次修改。 正常的状态变化 1. pending -> fulfilled 2. pending -> rejected ## then方法的同步执行 1. then方法接收两个参数,第一个参数是成功的回调函数,第二个参数是失败的回调函数。 2. 当执行器函数中没有异步代码时,then方法是能够获取到Promise的成功或失败状态的。此时可以根据成功或失败状态来执行对应的回调函数,回调函数的参数就是Promise的结果值。 ## then方法的异步执行 1. 当执行器函数中存在异步代码时,因为then方法是同步调用的此时Promise的状态仍然为pending初始状态。 2. 执行then方法Promise状态仍然为pending时,就无法根据成功或失败状态来执行对应的回调方法。此时保存回调方法,等异步代码执行完毕,Promise状态变化时,再执行回调方法。 ## then方法的多次执行 一个Promise实例可以指定多个then方法,当Promise实例对象的状态变化时如果存在多个then方法,那么所有then方法的回调都会执行。 ## then方法的返回结果 then方法的返回结果是一个Promise对象,Promise对象的状态和返回值受回调函数的执行结果影响。 1. 回调函数的执行结果不是Promise对象时,then执行结果Promise的状态为成功状态,结果值就是回调函数的执行结果。 2. 回调函数的执行结果是Promise对象时,then执行结果Promise的状态、结果值和回调函数的执行结果Promise保持一致。 3. 回调函数执行抛出异常时,then执行结果Promise的状态为失败状态,结果值就是抛出的异常信息。 ## then的链式调用 因为then方法的执行结果是一个Promise对象,所以可以进行链式调用。 如 new Promise((resolve,reject)=>{}).then().then()... ## then方法的值传递 then方法调用时可以不传回调参数,结果值会传递到下一个then。 ## catch方法 1. then方法调用时可以不传错误回调函数,如果有错误会被catch方法捕获。 2. catch方法就是then(undefined, onRejected)的语法糖。 ## Promise的值传递和异常穿透 值传递和异常穿透的原理就是如果传入的回调参数不是函数类型时会设置默认的函数进行处理。 值传递 ```javascript // then方法值传递 if (typeof onResolved !== 'function') { onResolved = value => value } ``` 异常穿透 ```javascript // then方法异常穿透 if (typeof onRejected !== 'function') { onRejected = reason => { throw reason } } ``` ## resolve方法 resolve方法是Promise函数对象上的一个方法,返回值是一个Promise对象,状态和结果值受resolve方法参数的影响。 1. resolve方法参数不是Promise对象时,返回值Promise的状态为成功状态,结果值就是接收的参数。 2. resolve方法参数是Promise对象时,返回值Promise的状态、结果值和resolve方法参数的Promise对象保持一致。 ## reject方法 reject方法是Promise函数对象上的一个方法,返回值是一个失败状态的Promise对象,结果值就是reject方法传入的参数。 ## all方法 all方法是Promise函数对象上的一个方法,参数是一个Promise类型的数组,返回值Promise受数组中Promise的影响。 1. all方法的参数数组中Promise的状态都为成功,则返回值Promise的状态为成功。结果值是一个数组,存的是all方法参数Promise类型数组中所有Promise成功的结果值。 2. all方法的参数数组中有一个Promise的状态为失败,则返回值Promise的状态为失败,结果值就是all方法的参数数组中失败的Promise的结果值。 ## race方法 race方法是Promise函数对象上的一个方法,参数是一个Promise类型的数组,返回值Promise的状态、结果值与数组中最先改变状态的Promise保持一致。 ## 任务的执行顺序 同步任务:从上到下依次执行。 异步任务:异步任务被分为两种类型。 1. 一种是宏任务,例如:setTimeout,setInterval...等。 2. 一种是微任务,例如:MutationObserver,Promise.then...等。 浏览器执行代码时先执行同步任务,异步任务优先执行微任务,等没有微任务之后再执行宏任务。 3. 任务优先级 同步任务 > 微任务 > 宏任务 ## then方法回调函数的执行顺序 then方法回调函数的执行是异步执行的,当Promise状态变化的时候会将回调任务添加到微任务队列。 ## Promise封装class版 需要注意的几点 1. executor执行器函数放到constructor构造函数中执行 2. then、catch为实例方法,供实例对象调用 3. resolve、reject、all、race为静态方法,class对象无需实例化即可调用,这些方法需要使用static关键字修饰 ## async 关键字 经过async关键字修饰过的函数,返回的是一个Promise对象,结果值、状态受return值影响。 1. return值是非Promise对象,返回的Promise状态是成功状态,结果值就是return值。 2. return值是Promise对象,返回的Promise状态、结果值和return值Promise保持一致。 3. throw异常,返回的Promise是失败状态,结果值就是throw的异常。 ## await 关键字 await关键字用来修饰一个对象,如果修饰的是Promise对象,Promise状态在未改变之前程序会一直等待。 async函数中可以没有await,但是await必须在async修饰的函数中使用。 1. 如果修饰的是非Promise对象,返回值是原值。 2. 如果修饰的是成功状态的Promise对象,返回值是Promise的结果值。 3. 如果修饰的是失败状态的Promise对象,结果值需要使用try catch进行捕获。 4. 如果修饰的是throw异常的Promise对象,异常信息需要使用try catch进行捕获。