Promise
Promise
优点:解决并发问题(同步多个异步方法的执行结果)。解决链式调用的问题(先获取a,在获取b) 解决多个回调嵌套的问题。缺点:promise无法终止,只能说是抛弃本次promise的结果。
1. A+规范
- new Promise时,需要传递一个 executor 执行器,执行器立刻执行。
- executor 接受两个参数,分别是 resolve 和 reject。
- promise 只能从 pending 到 rejected, 或者从 pending 到 fulfilled。
- promise 的状态一旦确认,就不会再改变。
- promise 都有 then 方法,then 接收两个参数,分别是 promise 成功的回调 onFulfilled, 和 promise 失败的回调 onRejected。
- 如果调用 then 时,promise已经成功,则执行 onFulfilled,并将promise的值作为参数传递进去。 如果promise已经失败,那么执行 onRejected, 并将 promise 失败的原因作为参数传递进去。如果promise的状态是pending,需要将onFulfilled和onRejected函数存放起来,等待状态确定后,再依次将对应的函数执行(发布订阅)。
- then 的参数 onFulfilled 和 onRejected 可以缺省。
- promise 可以then多次,promise 的then 方法返回一个 promise。
- 如果 then 返回的是一个结果,那么就会把这个结果作为参数,传递给下一个then的成功的回调(onFulfilled)。
- 如果 then 中抛出了异常,那么就会把这个异常作为参数,传递给下一个then的失败的回调(onRejected)。
- 如果 then 返回的是一个promise,那么需要等这个promise,那么会等这个promise执行完,promise如果成功,就走下一个then的成功,如果失败,就走下一个then的失败。
- 如果 onFulfilled 或者 onRejected 返回一个值 x ,则运行下面的 Promise 解决过程:。
- 如果 onFulfilled 或者 onRejected 抛出一个异常 e ,则 promise2 必须拒绝执行,并返回拒因 e。
- 如果 onFulfilled 不是函数且 promise1 成功执行, promise2 必须成功执行并返回相同的值。
- 如果 onRejected 不是函数且 promise1 拒绝执行, promise2 必须拒绝执行并返回相同的据因。
2. promise测试
npm i promises-aplus-tests -g
在
promise.js
增加以下代码Promise.deferred = function(){ let dfd = {}; dfd.promise = new Promise((resolve,reject)=>{ dfd.resolve = resolve; dfd.reject = reject; }); return dfd; }
promises-aplus-tests promise.js
3. catch
捕获失败的peomise。
4. Promise.finally
无论如何都执行,finally会传递前一个promise的结果但不会接管该结果,如果finally返回的是promise会等待这个promise执行完成。
5. Promise.try
能捕获同步或者异步异常。需要自己实现。
6. Promise.resolve
返回成功的promise。
7. Promise.reject
返回失败的pomise。
8. Promise.all
返回promise。全部完成才算完成,如果有一个失败,就失败。Promise.all是按照顺序执行的。
9. Promise.race
有一个成功就成功,有一个失败就失败。
10. Promise.stop
终止一个promise。
11. PromiseA+实现
const PENDING = 'PENDING'; const FULFILLED = 'FULFILLED'; const REJECTED = 'REJECTED'; const resolvePromise = (promise2, x, resolve, reject) => { if (promise2 === x) { return reject(new TypeError()); } if ((x !== null && typeof x === 'object') || typeof x === 'function') { let isCalled = false; try { let then = x.then; if (typeof then === 'function') { then.call(x, y => { if (isCalled) return; isCalled = true; resolvePromise(promise2, y, resolve, reject) }, r => { if (isCalled) return; isCalled = true; reject(r); }) } else { resolve(x); } } catch (e) { if (isCalled) return; isCalled = true; reject(e) } } else { resolve(x); } } class Promise { constructor(executor) { this.status = PENDING; this.value = null; this.reason = null; this.onFulfilledCallbacks = []; this.onRejectedCallbacks = []; let resolve = value => { if (this.status === PENDING) { if (value instanceof Promise) { return value.then(resolve, reject); } this.status = FULFILLED; this.value = value; this.onFulfilledCallbacks.forEach(fn => fn()) } } let reject = reason => { if (this.status === PENDING) { this.status = REJECTED; this.reason = reason; this.onRejectedCallbacks.forEach(fn => fn()) } } try { executor(resolve, reject); } catch (e) { reject(e) } } then(onFulfilled, onRejected) { onFulfilled = typeof onFulfilled == 'function' ? onFulfilled : value => value; onRejected = typeof onRejected == 'function' ? onRejected : err => { throw err }; let promise2 = new Promise((resolve, reject) => { if (this.status === FULFILLED) { setTimeout(() => { try { let x = onFulfilled(this.value); resolvePromise(promise2, x, resolve, reject); } catch (e) { reject(e) } }) } if (this.status === REJECTED) { setTimeout(() => { try { let x = onRejected(this.reason); resolvePromise(promise2, x, resolve, reject); } catch (e) { reject(e) } }) } if (this.status === PENDING) { this.onFulfilledCallbacks.push(() => { setTimeout(() => { try { let x = onFulfilled(this.value); resolvePromise(promise2, x, resolve, reject); } catch (e) { reject(e) } }) }); this.onRejectedCallbacks.push(() => { setTimeout(() => { try { let x = onRejected(this.reason); resolvePromise(promise2, x, resolve, reject); } catch (e) { reject(e) } }) }); } }); return promise2; } catch(onRejected) { return this.then(null, onRejected); } static all(promises) { return new Promise((resolve, reject) => { let values = [], index = 0, len = promises.length; promises.forEach((promise, i) => { Promise.resolve(promise).then((v) => { values[i] = v; ++index === len ? resolve(values) : null; }, reject) }) }) } static resolve(value) { return new Promise((resolve) => { resolve(value); }) } static reject(value) { return new Promise((resolve, reject) => { reject(value); }) } finally(fn) { return this.then(v => Promise.resolve(fn()).then(() => v), e => Promise.resolve(fn()).then(() => { throw e })); } static stop(promise) { let fail; let promise2 = new Promise((resolve, reject) => { fail = reject; }) let race = Promise.race([promise2, promise]); race.reject = fail; return race; } static try(fn) { return new Promise((resolve, reject) => { resolve(fn()) }) } static race(promises) { return new Promise((resolve, reject) => { promises.forEach(promise => { Promise.resolve(promise).then(resolve, reject); }) }) } } Promise.deferred = function () { const dfd = {}; dfd.promise = new Promise((resolve, reject) => { dfd.resolve = resolve; dfd.reject = reject; }) return dfd; } module.exports = Promise;
相关推荐
nmgxzm00 2020-11-10
xixixi 2020-11-11
88254251 2020-11-01
MarukoMa 2020-09-02
88234852 2020-09-15
陈旭阳 2020-08-31
whynotgonow 2020-08-19
前端开发Kingcean 2020-07-30
whynotgonow 2020-07-29
bowean 2020-07-08
前端开发Kingcean 2020-07-08
88520191 2020-07-05
前端开发Kingcean 2020-06-27
88481456 2020-06-18
whynotgonow 2020-06-16
88520191 2020-06-13
88520191 2020-06-13
89500297 2020-06-13