Promise对象用于异步计算。一个Promise对象表明着一个还未完成,但预期未来会完成的操做。git
Note:es6
Promise原理分析二github
Promise对象有如下几种状态:segmentfault
pending: 初始状态, 既不是 fulfilled 也不是 rejected.设计模式
fulfilled: 成功的操做.promise
rejected: 失败的操做.异步
pending状态的Promise对象既可转换为带着一个成功值的fulfilled状态,也可变为带着一个失败信息的 rejected状态。当状态发生转换时,Promise.then绑定的方法就会被调用。(当绑定方法时,若是 Promise对象已经处于fulfilled或rejected状态,那么相应的方法将会被马上调用,因此在异步操做的完成状况和它的绑定方法之间不存在竞争条件。)函数
由于Promise.prototype.then和Promise.prototype.catch方法返回Promises对象, 因此它们能够被链式调用。ui
语法this
new Promise(executor); new Promise(function(resolve, reject) { ... });
参数
name | desc |
---|---|
executor | 带有resolve、reject两个参数的函数对象。第一个参数用在处理执行成功的场景,第二个参数则用在处理执行失败的场景。一旦咱们的操做完成便可调用这些函数。 |
构造函数主要完成状态的初始化,并提供resolve
和reject
两个方法给建立者以转变状态。
const utils = require('./utils'); const isFunction = utils.isFunction; const STATUS = { PENDING: 'pending', FULFILLED: 'fulfilled', REJECTED: 'rejected' }; const SYMBOL_STATUS = Symbol('status'); const SYMBOL_DATA = Symbol('data'); const SYMBOL_FULFILLED_CALLBACK = Symbol('fulfilledCallback'); const SYMBOL_REJECTED_CALLBACK = Symbol('rejectedCallback'); class Promise { constructor(executor) { if (!isFunction(executor)) { throw Error(`Promise executor ${executor} is not a function`); } const self = this; // 初始状态为pending const status = self[SYMBOL_STATUS] = STATUS.PENDING; // 使用symbol实现私有化 self[SYMBOL_FULFILLED_CALLBACK] = undefined; self[SYMBOL_REJECTED_CALLBACK] = undefined; self[SYMBOL_DATA] = undefined; function resovle(value) { // todo } function reject(reason) { // todo } // 执行executor函数,若出现异常则调用reject方法,将状态变为rejected,同时调用回调函数 try { executor(resovle, reject); } catch (err) { reject(err); } } }
上面代码中完成了构造函数的雏形,而resolve
和reject
两个函数的职责为状态转变和回调函数的调用:
resolve,接受一个成功值,传递给绑定的fulfilled回调函数中。主要工做是将当前状态变为fulfilled
状态,同时调用绑定的fulfilled回调函数:
function resovle(value) { const fulfilledCallback = self[SYMBOL_FULFILLED_CALLBACK]; if (status === STATUS.PENDING) { self[SYMBOL_STATUS] = STATUS.FULFILLED; // 状态转换 self[SYMBOL_DATA] = value; // 保存成功值 if (isFunction(fulfilledCallback)) { setTimeout(() => { // 不阻塞主流程,在下一个事件轮询中再调用fulfilled回调函数 fulfilledCallback(value); }); } } }
reject,接受一个失败信息,传递给绑定的rejected回调函数中。主要工做是将当前状态变为rejected
状态,同时调用绑定的rejected回调函数:
function reject(reason) { const rejectedCallback = self[SYMBOL_REJECTED_CALLBACK]; if (status === STATUS.PENDING) { self[SYMBOL_STATUS] = STATUS.REJECTED; // 状态转换 self[SYMBOL_DATA] = reason; // 保存成功值 if (isFunction(rejectedCallback)) { setTimeout(() => { // 不阻塞主流程,在下一个事件轮询中再调用rejected回调函数 rejectedCallback(reason); }); } } }
fulfilled`和rejected回调函数是经过Promise.prototype.then和Promise.prototype.catch注册的。
then方法返回一个Promise。它有两个参数,分别为Promise在成功和失败状况下的回调函数。
语法
p.then(onFulfilled, onRejected); p.then(function(value) { // todo }, function(reason) { // todo });
参数
name | desc |
---|---|
onFulfilled | 一个函数,当Promise的状态为fulfilled时调用。该函数有一个参数,为成功的返回值。 |
onRejected | 一个函数,当Promise的状态为rejected时调用。该函数有一个参数,为失败的缘由。 |
根据当前状态对回调函数进行处理,同时返回一个新的Promise对象,以便链式调用。
then(onFulfilled, onRejected) { const self = this; const status = self[SYMBOL_STATUS]; const data = self[SYMBOL_DATA]; const resolveValue = self[SYMBOL_RESOLVE_VALUE]; // 若是onFulfilled不是函数,回调函数仅返回成功值 const fulfilledCallback = isFunction(onFulfilled) ? onFulfilled : function returnFunc(value) { return value; }; // 若是onRejected不是函数,回调函数仅返回失败信息 const rejectedCallback = isFunction(onRejected) ? onRejected : function throwFunc(reason) { throw reason; }; // 当前状态为pending if (status === STATUS.PENDING) { // 返回一个新的Promise对象,能够被链式调用 return new Promise((resolve, reject) => { // 将fulfilled回调函数注册到当前Promise对象中(非新Promise对象) self[SYMBOL_FULFILLED_CALLBACK] = value => { // 根据回调函数的执行状况,经过传递的新Promise对象的resolve和reject方法对其状态进行转变 try { const newValue = fulfilledCallback(value); // 解析成功值 resolveValue(newValue, resolve, reject); } catch (err) { reject(err); } }; // 同上 self[SYMBOL_REJECTED_CALLBACK] = reason => { try { const newReason = rejectedCallback(reason); resolveValue(newReason, resolve, reject); } catch (err) { reject(err); } }; }); } // 当前状态为fulfilled if (status === STATUS.FULFILLED) { // 返回一个新的Promise对象,能够被链式调用 return new Promise((resolve, reject) => { // 在下一个事件轮询中当即调用fulfilled回调函数,根据执行状况决定新Promise对象的状态转变 setTimeout(() => { try { const newValue = fulfilledCallback(data); resolveValue(newValue, resolve, reject); } catch (err) { reject(err); } }); }); } // 当前状态为rejected if (status === STATUS.REJECTED) { // 返回一个新的Promise对象,能够被链式调用 return new Promise((resolve, reject) => { // 在下一个事件轮询中当即调用rejected回调函数,根据执行状况决定新Promise对象的状态转变 setTimeout(() => { try { const newReason = rejectedCallback(data); resolveValue(newReason, resolve, reject); } catch (err) { reject(err); } }); }); } } // 解析传递值函数 [SYMBOL_RESOLVE_VALUE](value, resolve, reject) { // 若传递值为Promise对象,将新Promise对象的resolve和reject传递给Promise传递值以触发状态的转换 if (value instanceof Promise) { value.then(resolve, reject); return; } // 若传递值不是Promise对象,传递给resolve方法 resolve(value); }
根据当前Promise对象的状态,对回调函数进行注册或当即执行,同时返回一个新的Promise对象。
pending,注册回调函数到当前的Promise对象中
fulfilled或rejected,当即执行回调函数
catch方法只处理Promise被拒绝的状况,并返回一个Promise。该方法的行为和调用Promise.prototype.then(undefined, onRejected)相同。
语法
p.catch(onRejected); p.catch(function(reason) { // todo });
参数
name | desc |
---|---|
onRejected | 当Promise被拒绝时调用的函数。该函数调用时会传入一个参数:失败缘由。 |
catch方法是对then方法的包装,仅传递onRejected失败回调函数。
catch(onRejected) { return this.then(null, onRejected); }
如今回顾下Promise的实现过程,其主要使用了设计模式中的观察者模式:
经过Promise.prototype.then和Promise.prototype.catch方法将观察者方法注册到被观察者Promise对象中,同时返回一个新的Promise对象,以即可以链式调用。
被观察者管理内部pending、fulfilled和rejected的状态转变,同时经过构造函数中传递的resolve和reject方法以主动触发状态转变和通知观察者。
MDN
ruanyifeng
百度百科