1

基本上,我需要的是在实际创建 Deferred 之前公开它。例如,假设我有一些包装了 Ajax 查询的对象,但在它开始之前它需要公开一个表示该查询解析的 Deferred:

var object = new AjaxRunningThing();
// Get a Deferred wrapping the Ajax operation
var ajaxResult = object.getAjaxResult();

// Later...

// Now the object is going to initiate the Ajax request
object.startAjax();

现在我只是手动将它们链接起来,以便“真实”延迟的分辨率被链接到“立面”之一:

// in getAjaxResult()
var publicDeferred = $.Deferred();

// in startAjax()
var privateDeferred = $.ajax(...);
privateDeferred.then(
    function() { publicDeferred.resolve.apply(this, arguments); },
    function() { publicDeferred.reject.apply(this, arguments); }
);

不过,我不禁认为有更好的方法可以做到这一点。

- 编辑 - -

仔细想想,我正在寻找的实际上是一个代理——搜索“代理”让我找到了这篇文章,它描述了我正在寻找的内容,并包含了一个更好的(尽管仍然不是完全透明的)解决方案:传播JQuery.Deferred 对象之间的事件

4

2 回答 2

0

在级联中解决 Promise 非常简单。我们一直都在看到它,很多时候只要一个承诺就足够了。您在这里需要的可以称为“延迟的法律模式”(与“延迟的反模式”相反)。

对我来说,这更多是关于如何分解代码,而不是简单地编写级联代码。

这是一种可能的方法:

function getLatentAjaxPromise(options) {
    var dfrd = $.Deferred(),
        promise = dfrd.promise(),
        jqXHR;

    // monkeypatch the promise with a `go()` method.
    promise.go = function(opts) {
        if(!jqXHR) { // in case .go() is called more than once.
            jqXHR = $.ajax($.extend(options, opts)).then(dfrd.resolve, dfrd.reject);
        }
        return promise;
    };
    return promise;
};

这将允许:

  • Deferred 对象本身要保持私有,
  • 要传递给getLatentAjaxPromise和/或的ajax选项.go
  • 承诺链将建立在getLatentAjaxPromise()和/或.go().

调用如下:

var latentAjaxPromise = getLatentAjaxPromise(...).then(...);

//and later ...
latentAjaxPromise.go(...).then(...);

双承诺链不应该有任何不良后果,尽管你可能需要保持你的智慧。从消费者的角度来看,两个连锁店都源于同一个承诺并不是很明显。

我很想看看是否有人能在这里发现任何明显的逻辑缺陷。

于 2015-02-28T20:41:44.780 回答
0

只是为了结束,这是我结束的解决方案。它在这里使用其他答案中的片段,但这是我需要的功能:

// Private deferred that will be resolved when the Ajax is complete
var _done = $.Deferred();
// Expose the deferred as a promise, so it's read-only to other components
var done = _done.promise();

// ... other components add their own callbacks to `done`

// Later, run the ajax, and resolve the deferred based on that
$.ajax(...).then(
    _done.resolve, _done.reject, _done.notify);
于 2015-03-13T21:21:26.850 回答