Promise/A+規範是什麼
Promise表示一個異步操作的最終結果。與Promise最主要的互動方法是通過将函數傳入它的then方法進而擷取得Promise最終的值或Promise最終最拒絕(reject)的原因。具體詳細的講解請移步:
- wikipedia上的介紹
-官方介紹網址
簡單的實作代碼
'use strict';
Promise = () => {};
var isPromise = (value) => {
return value instanceof Promise;
};
var defer = () => {
var pending = [], value;
var promise = new Promise();
promise.then = (callback) => {
if (pending) {
pending.push(callback);
} else {
callback(value);
}
};
return {
resolve: function (_value) {
if (pending) {
value = _value;
for (var i = , ii = pending.length; i < ii; i++) {
var callback = pending[i];
callback(value);
}
pending = undefined;
}
},
promise: promise
};
};
github上找到的一篇更加詳細的實作:github位址
更加詳細的代碼實作(對應将中文翻譯成為了中文):
(function() {
'use strict';
// 用于異步執行 onFulfilled/onRejected
// `setImmediate` or `function(fn) { setTimeout(fn,) }` in browser
// `process.nextTick` in node
var asyncCall = process.nextTick;
//
// Promise解析過程 是以一個promise和一個值做為參數的抽象過程,可表示為[[Resolve]](promise, x)
function resolve(promise, x) {
//.1
// 如果promise 和 x 指向相同的值, 使用 TypeError做為原因将promise拒絕
if (promise === x) {
return promise.reject(new TypeError('The promise and its value refer to the same object'));
}
//.3
// 如果x是一個對象或一個函數
if (x && (typeof x === 'function' || typeof x === 'object')) {
//.3.3
// 如果 resolvePromise 和 rejectPromise 都被調用了,或者被調用了多次,則隻第一次有效,後面的忽略。
// 我們用 called 作為辨別防止被多次調用
var called = false,then;
try { //.3.1 // 将 then 賦為 x.then then = x.then; if (typeof then === 'function') { //.3.3 // 如果 then 是一個函數,以x為this調用then函數,且第一個參數是resolvePromise,第二個參數是rejectPromise then.call(x, function(y) { //.3.3.1 // 當 resolvePromise 被以y為參數調用,執行 [[Resolve]](promise, y) if (!called) { called = true; resolve(promise, y); } }, function(r) { //.3.3.2 // 當 rejectPromise 被以 r 為參數調用,則以r為原因将promise拒絕。 if (!called) { called = true; promise.reject(r); } }); }else { //.3.4 // 如果 then不是一個函數,則 以x為值fulfill promise promise.fulfill(x); } }catch (e) { //.3.2 // 如果在取x.then值時抛出了異常,則以這個異常做為原因将promise拒絕 if (!called) { called = true; promise.reject(e); } }
}else {
//.4
// 如果 x 不是對象也不是函數,則以x為值 fulfill promise
promise.fulfill(x);
}
}
function Taxi() {
// pending, fulfilled, rejected
var _state =,
_value,
_onFulfills = [],
_onRejects = [];
this.done = function(onFulfilled, onRejected) {
if (_state ===) {// 如果還在pending,先把處理函數存起來 _onFulfills.push(onFulfilled); _onRejects.push(onRejected); }else {// 否則,異步執行 asyncCall(function() { if (_state ===) { if (typeof onFulfilled === 'function') { onFulfilled(_value); } }else if (typeof onRejected === 'function') { onRejected(_value); } }); }
};
/**
* 用于this.fulfill和this.reject内部調用的函數
* @param {number} state->pending,->fulfill,->reject
* @param {dynamic} value result 或 reason
*/
function _complete(state, value){
// 隻能 fulfill或reject一次, 後面的忽略
if (!_state) { _state = state; _value = value; // 根據 state 擷取需要處理的函數數組 // 異步執行 asyncCall(function() { var handlers = state == ? _onFulfills : _onRejects; handlers.forEach(function(fn) { if (typeof fn === 'function') { fn(value); } }); // 執行完之後,解除數組引用 _onFulfills = null; _onRejects = null; }); }
}
this.fulfill = function(value) {
_complete(1, value);
};
this.reject = function(value) {
_complete(2, value);
};
}
Taxi.prototype = {
constructor: Taxi,
catch: function(onRejected) {
this.then(null, onRejected);
},
then: function(onFulfilled, onRejected) {
//.7
// then 必須傳回一個promise
// 是以我們new一個,等下用于傳回
var taxi = new Taxi();
// this指向目前promise
//.2
// 如果onFulfilled是一個函數:
// 它必須在promise fulfilled後調用, 且promise的value為其第一個參數。
//.3
// 如果onRejected是一個函數,
// 它必須在promise rejected後調用, 且promise的reason為其第一個參數。
this.done(function(x) { if (typeof onFulfilled === 'function') { try { //.7.1 // 如果onFulfilled 或 onRejected 傳回了值x, // 則執行Promise 解析流程[[Resolve]](promise2, x). resolve(taxi, onFulfilled(x)); }catch (e) { //.7.2 // 如果onFulfilled 或 onRejected抛出了異常e, // 則promise2應當以e為reason被拒絕 taxi.reject(e); } }else { //.7.3 // 如果 onFulfilled 不是一個函數且promise1已經fulfilled, // 則promise2必須以promise1的值fulfilled. taxi.fulfill(x); } }, function(x) { if (typeof onRejected === 'function') { try { //.7.1 // 如果onFulfilled 或 onRejected 傳回了值x, // 則執行Promise 解析流程[[Resolve]](promise2, x). resolve(taxi, onRejected(x)); }catch (e) { //.7.2 // 如果onFulfilled 或 onRejected抛出了異常e, // 則promise2應當以e為reason被拒絕 taxi.reject(e); } }else { //.7.4 // 如果 OnReject 不是一個函數且promise1已經rejected, // 則promise2必須以相同的reason被拒絕. taxi.reject(x); } });
return taxi;
}
};
module.exports = Taxi;
}());
更多的實作版本
bluebird
q – Angularjs的$q對象是q的精簡版