5
我見過,看起來像這樣的代碼幾位近期:添加一個方法,然後給一個函數回調
myFunc(args).then(function() { ... });
我覺得這句法回調真的優雅。我的理解是,這不是vanilla JS的一部分,我希望能夠偶爾使用它,而不依賴於特定的庫,所以我對如何自己實現這一點感興趣。那麼,這種事情是如何工作的,以及如何爲函數調用實現它?
我見過,看起來像這樣的代碼幾位近期:添加一個方法,然後給一個函數回調
myFunc(args).then(function() { ... });
我覺得這句法回調真的優雅。我的理解是,這不是vanilla JS的一部分,我希望能夠偶爾使用它,而不依賴於特定的庫,所以我對如何自己實現這一點感興趣。那麼,這種事情是如何工作的,以及如何爲函數調用實現它?
這種模式被稱爲「承諾」。它通過jQuery和dojo等實現,一種方法是查看它們的代碼並查看它們是如何實現的。
一般實現模式是創建一個函數,該函數返回一個對象,該對象包含一個函數(然後)將一對函數作爲回調函數傳遞給先前的方法,然後在成功或失敗時運行該方法。 MSDN有更多關於在blog post here
承諾有張貼在Github上這裏極簡實現:Promises GIST
function Promise() {
this._thens = [];
}
Promise.prototype = {
/* This is the "front end" API. */
// then(onResolve, onReject): Code waiting for this promise uses the
// then() method to be notified when the promise is complete. There
// are two completion callbacks: onReject and onResolve. A more
// robust promise implementation will also have an onProgress handler.
then: function (onResolve, onReject) {
// capture calls to then()
this._thens.push({ resolve: onResolve, reject: onReject });
},
// Some promise implementations also have a cancel() front end API that
// calls all of the onReject() callbacks (aka a "cancelable promise").
// cancel: function (reason) {},
/* This is the "back end" API. */
// resolve(resolvedValue): The resolve() method is called when a promise
// is resolved (duh). The resolved value (if any) is passed by the resolver
// to this method. All waiting onResolve callbacks are called
// and any future ones are, too, each being passed the resolved value.
resolve: function (val) { this._complete('resolve', val); },
// reject(exception): The reject() method is called when a promise cannot
// be resolved. Typically, you'd pass an exception as the single parameter,
// but any other argument, including none at all, is acceptable.
// All waiting and all future onReject callbacks are called when reject()
// is called and are passed the exception parameter.
reject: function (ex) { this._complete('reject', ex); },
// Some promises may have a progress handler. The back end API to signal a
// progress "event" has a single parameter. The contents of this parameter
// could be just about anything and is specific to your implementation.
// progress: function (data) {},
/* "Private" methods. */
_complete: function (which, arg) {
// switch over to sync then()
this.then = which === 'resolve' ?
function (resolve, reject) { resolve(arg); } :
function (resolve, reject) { reject(arg); };
// disallow multiple calls to resolve or reject
this.resolve = this.reject =
function() { throw new Error('Promise already completed.'); };
// complete all waiting (async) then()s
var aThen, i = 0;
while (aThen = this._thens[i++]) { aThen[which] && aThen[which](arg); }
delete this._thens;
}
};
(請注意,這不是我的代碼,通過它看上去和它看起來不錯的起點。 ,但所有功勞都歸功於original author)
'then'方法往往是「承諾」模式的一部分。 jQuery將其實現爲「延遲」api的一部分。 – zzzzBov 2013-02-10 01:55:00
[道格拉斯克羅克福德在他的「Monads和Gonads」談話中簡單地接觸了諾言](http://www.youtube.com/watch?v=dkZFtimgAcM&t=1920) – zzzzBov 2013-02-10 01:58:05
閱讀關於CommonJS承諾建議,其中還包括一個庫列表你可以使用:http://wiki.commonjs.org/wiki/Promises/A。 – 2013-02-10 03:32:39