We read every piece of feedback, and take your input very seriously.
To see all available qualifiers, see our documentation.
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
在学习源码之前,建议您先通读并学习以下知识点
学习完以上手册后如果想继续加深学习,可以看这个精彩的讲解视频!
Promise 是微任务,setTimeout 是宏任务,同一个事件循环中,promise总是先于 setTimeout 执行。
Promise的构造函数是同步执行的。then中的方法是异步执行的。
构造函数是同步执行
then中的方法是异步执行
promise有三种状态: fulfilled, rejected, pending.
Promise 的优点:
Promise 的缺点:
如果您已经学习完以上内容,那么Let‘s go!
const PENGING = 'PENGING', FULFILLED = 'FULFILLED', REJECTED = 'REGECTED'; function _Promise (executor){ this.status = PENGING; this.value = undefined; this.reason = undefined; this.onFulFilledCallbacks = []; this.onRejectedCallbacks = []; const resolve = function(value){ if(this.status == PENGING){ this.status = FULFILLED; this.value = value; this.onFulFilledCallbacks.forEach(fn => fn()) //发布 } } const reject = function(reason){ if(this.status == PENGING){ this.status = REJECTED; this.reason = reason; this.onRejectedCallbacks.forEach(fn => fn()) //发布 } } try { // 捕获 new Promise((resolve, reject) => { throw new Error("有异常")}) 这种情况 executor(resolve, reject) } catch (error) { reject(err); } } _Promise.prototype.then = function(onFulFilled, onRejected){ if(this.status == FULFILLED){ onFulFilled(this.value); } if(this.status == REJECTED){ onRejected(this.reason); } // 1. 处理 new Promise((resolve, reject) => { setTimeOut(resolve, 0)}) 这种异步的情况 // 2. 处理多个 then 调用情况 if(this.status == PENGING){ // 订阅 this.onFulFilledCallbacks.push(() => { onFulFilled(this.value); }) this.onRejectedCallbacks.push(() => { onRejected(this.reason); }) } }
/** * 1. new Promise时,需要传递一个 executor 执行器,执行器立刻执行 * 2. executor 接受resolve 和 reject两个参数 * 3. promise 只能从 pending 到 rejected, 或者从 pending 到 fulfilled * 5. 调用 then 时,如果是成功,则执行 onFulfilled。 * 如果失败,那么执行 onRejected。 * 如果promise的状态是pending,则需要使用 发布订阅 * 6. then 的参数 onFulfilled 和 onRejected 可以缺省 * 7. 多个promise嵌套时候执行最里面的promise的resolve或者reject */ const PENDING = 'PENDING', FULFILLED = 'FULFILLED', REJECTED = 'REJECTED'; function Promise(excutor) { this.status = PENDING; this.value = undefined; this.reason = undefined; this.resolveCallbacks = []; // 成功的回调集合,即发布 this.rejectCallbacks = []; // 失败的回调集合,即发布 let self = this; const resolve = function (value) { if (self.status === PENDING) { self.status = FULFILLED; self.value = value; self.resolveCallbacks.forEach(fn => fn()); } } const reject = function (reason) { if(self.status === PENDING){ self.status = REJECTED; self.reason = reason; self.rejectCallbacks.forEach(fn => fn()); } } try{ // 防止excutor语句有throw Error excutor(resolve, reject); }catch(e){ reject(e); } } Promise.prototype.then = function (onFulfilled, onRejected) { // onFulfilled、onRejected没传值时候手动赋值,处理then().then().then().then((value)=>{},(reason)=>{})这种情况 onFulfilled = typeof onFulfilled === 'function'? onFulfilled: value => value; // throw会被外层的catch捕获 onRejected = typeof onRejected === 'function'? onRejected: reason => {throw reason}; let self = this; let promise2 = new Promise((resolve, reject) => { if(self.status === FULFILLED){ // 通过使用宏任务setTimeout使内部的resolvePromise函数可以使用promise2, // 否则promise2内部无法使用自己 setTimeout(() => { try { let x = onFulfilled(self.value); // 判断x是promise类型还是常量 resolvePromise(promise2, x, resolve, reject); } catch (e) { reject(e); } }, 0); } if(self.status === REJECTED){ setTimeout(() => { try { let x = onRejected(self.reason); // 判断x是promise类型还是常量 resolvePromise(promise2, x, resolve, reject); } catch (e) { reject(e); } }, 0); } // 该分支处理的是异步请求时候,即没有立即执行resolvePromise,所以异步请求时候可以正常使用promise2,所以不用setTimeout包resolvePromise函数 if(self.status === PENDING){ self.resolveCallbacks.push(() => { // 订阅 try { let x = onFulfilled(self.value); // 判断x是promise类型还是常量 resolvePromise(promise2, x, resolve, reject); } catch (e) { reject(e); } }) self.rejectCallbacks.push(() => { // 订阅 try { let x = onRejected(self.reason); // 判断x是promise类型还是常量 resolvePromise(promise2, x, resolve, reject); } catch (e) { reject(e); } }) } }) return promise2; } function resolvePromise (promise2, x, resolve, reject) { if (promise2 === x) { return reject(new TypeError('chaining cycle')); } // call作用:防止出现下面resolve重复调用的情况,重复情况下只执行第一个resolve(1) // resolve(1); // resolve(2); let called = false; if ((typeof x === 'object' && x != null) || typeof x === 'function') { // let then = x.then可能报错 try { let then = x.then; // 判断x是promise类型还是常量 if (typeof then === 'function') { then.call(x, (y) => { if (called) return; called = true; resolvePromise(promise2, y, resolve, reject); }, (r) => { if (called) return; called = true; reject(r); }) } else { if (called) return; called = true; resolve(x); } } catch (e) { if (called) return; called = true; reject(e); } }else{ resolve(x); } } // catch 其实就是then的语法糖 // Promise中的then第二个参数和catch主要区别就是,如果在then的第一个函数里抛出了异常,后面的catch能捕获到, // 而then的第二个函数捕获不到。 Promise.prototype.catch = function(errCallback){ this.then(null, errCallback) } module.exports = Promise;
then的第二个参数和catch捕获错误信息的时候会就近原则,如果是promise内部报错,reject抛出错误后,then的第二个参数和catch方法都存在的情况下,只有then的第二个参数能捕获到,如果then的第二个参数不存在,则catch方法会捕获到。
写完以上主要代码后,可以使用promises-aplus-tests来测试所编写的代码是否符合PromiseA+的规范。
promises-aplus-tests
安装命令如下:
npm install -g promises-aplus-tests
如果我们的文件命名为test.js的话,那请在对应目录下执行以下命令
test.js
promises-aplus-tests test.js
Promise.resolve
Promise.resolve('foo') // 等价于 new Promise(resolve => resolve('foo'))
1、如果 value 是 thenable 对象(具有then方法的对象),将这个对象转为 Promise 对象,然后就立即执行thenable对象的then方法。 2、如果 value 是 promise 对象,则直接返回这个 promise 对象。 3、其他情况,直接返回以该值为成功状态的 promise 对象。
成功状态
Promise.resolve = function (data) { // 1 参数是一个 Promise 实例,不做任何修改、原封不动地返回这个实例 if (data instanceof Promise) { return data } // 2 参数是一个thenable对象,将这个对象转为 Promise 对象,然后就立即执行thenable对象的then方法。 if (data.then) { return new Promise((resolve, reject) => { data.then(resolve, reject) }) } // 3 参数不是具有then方法的对象,或根本就不是对象 // 4 不带有任何参数 return new Promise((resolve) => { resolve(data) }) }
Promise.reject
Promise.reject()方法会原封不动地返回reject的参数。
Promise.reject = function (reason) { return new Promise((resolve, reject) => { reject(reason); }); }
任何一个await语句后面的Promise对象变为reject状态,那么整个async函数都会中断执行。如果不catch,async函数直接抛出reject了,async里在await后面的代码是不会执行的。
await
Promise
reject
async
catch
一般写catch有以下几种方法(推荐使用第一种方法):
try catch
async function f() { try { await Promise.reject('出错了'); } catch(err) { console.log(err); } return await Promise.resolve('hello world'); } f().then(v => console.log(v)) // 出错了 // hello world
async function f() { await Promise.reject('出错了').catch(e => console.log(e)); return await Promise.resolve('hello world'); } f().then(v => console.log(v)) // 出错了 // hello world
Promise.all
1、传入一个Iterable,但大部分是数组。 2、如果有一个promise失败,那么Promise.all返回失败。 3、在任何情况下,Promise.all 返回的完成状态都是一个数组。
Promise.all = function (promises){ const arr = Array.from(promises); return new Promise((resolve, reject) => { const len = arr.length; const res = []; let count = 0; for(let i = 0; i < len; i++){ Promise.resolve(arr[i]).then(value => { res[i] = value; if(++count == len){ resolve(res); } }, reason => reject(reason)); } }) } Promise.all([2, 3, Promise.resolve(1)]).then(value => console.log(value)) // [2, 3, 1] Promise.all([2, 3, Promise.reject(4)]).then(value => console.log(value)).catch(r => console.log(r)) // 4
Promise.race
Promise.race([p1, p2, p3])里面哪个结果获得的快,就返回那个结果,不管结果本身是成功状态还是失败状态。 常用在开发程序与测速程序一起跑来判断开发程序的速度是否符合测速程序要求。
Promise.race = function(promises) { return new Promise(function(resolve, reject) { for (var i = 0; i < promises.length; i++) { Promise.resolve(promises[i]).then(function(value) { resolve(value) }, function(reason) { reject(reason) }) } }) } let p1 = new Promise((resolve, reject) => { setTimeout(() => { resolve('p1') }, 1000); }) let p2 = new Promise((resolve, reject) => { setTimeout(() => { resolve('p2') }, 2000); }) Promise.race([p1, p2]).then(data => { console.log(data); // p1 })
Promise.finally
不管成功还是失败,都会走到finally中,并且finally之后,还可以继续then。并且会将值原封不动的传递给后面的then.
Promise.prototype.finally = function (callback) { return this.then((value) => { return Promise.resolve(callback()).then(() => { return value; }); }, (err) => { return Promise.resolve(callback()).then(() => { throw err; }); }); }
The text was updated successfully, but these errors were encountered:
No branches or pull requests
Promise的源码实现
在学习源码之前,建议您先通读并学习以下知识点
学习完以上手册后如果想继续加深学习,可以看这个精彩的讲解视频!
Promise和setTimeout的区别 ?
Promise 是微任务,setTimeout 是宏任务,同一个事件循环中,promise总是先于 setTimeout 执行。
Promise构造函数是同步还是异步执行,then中的方法呢 ?
Promise的
构造函数是同步执行
的。then中的方法是异步执行
的。promise 有几种状态, Promise 有什么优缺点 ?
promise有三种状态: fulfilled, rejected, pending.
如果您已经学习完以上内容,那么Let‘s go!
简易版
完全版
then的第二个参数和catch捕获错误信息的时候会就近原则,如果是promise内部报错,reject抛出错误后,then的第二个参数和catch方法都存在的情况下,只有then的第二个参数能捕获到,如果then的第二个参数不存在,则catch方法会捕获到。
写完以上主要代码后,可以使用
promises-aplus-tests
来测试所编写的代码是否符合PromiseA+的规范。安装命令如下:
如果我们的文件命名为
test.js
的话,那请在对应目录下执行以下命令Promise的其他方法
1、如果 value 是 thenable 对象(具有then方法的对象),将这个对象转为 Promise 对象,然后就立即执行thenable对象的then方法。
2、如果 value 是 promise 对象,则直接返回这个 promise 对象。
3、其他情况,直接返回以该值为
成功状态
的 promise 对象。Promise.reject()方法会原封不动地返回reject的参数。
任何一个
await
语句后面的Promise
对象变为reject
状态,那么整个async
函数都会中断执行。如果不catch
,async
函数直接抛出reject
了,async
里在await
后面的代码是不会执行的。一般写
catch
有以下几种方法(推荐使用第一种方法):await
代码写在try catch
代码块中, 这样当await
抛出异常时直接被catch
捕获,不会影响下面代码的运行。await
后面的Promise
对象再跟一个catch
方法,处理前面可能出现的错误。1、传入一个Iterable,但大部分是数组。
2、如果有一个promise失败,那么Promise.all返回失败。
3、在任何情况下,Promise.all 返回的完成状态都是一个数组。
Promise.race([p1, p2, p3])里面哪个结果获得的快,就返回那个结果,不管结果本身是成功状态还是失败状态。
常用在开发程序与测速程序一起跑来判断开发程序的速度是否符合测速程序要求。
不管成功还是失败,都会走到finally中,并且finally之后,还可以继续then。并且会将值原封不动的传递给后面的then.
The text was updated successfully, but these errors were encountered: