包装jQuery的模式延迟了另一个延迟?

时间:2013-08-01 19:22:40

标签: jquery jquery-deferred

基本上,我需要在实际创建之前公开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); }
);

我不禁想到有更好的方法可以做到这一点。

- 编辑---

考虑更多,我正在寻找的是真正的代理 - 搜索“代理”引导我阅读这篇文章,其中描述了我正在寻找的内容并包含更好的内容(尽管仍然不完全透明)解决方案:Propagating events between JQuery.Deferred objects

2 个答案:

答案 0 :(得分:0)

解决级联中的承诺非常简单。我们一直都会看到这一点,通常只有一个承诺就足够了。你在这里需要什么可以被称为"延迟法律模式" (而不是"延迟反模式")。

对我而言,这更多的是关于如何将代码考虑在内而不仅仅是对级联进行编码。

这是一种可行的方法:

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和/或.go
  • 的ajax选项
  • 将承诺链构建到getLatentAjaxPromise()和/或.go()

请致电如下:

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

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

双胞胎承诺链不应该有任何不良后果,尽管你可能需要保持对你的智慧。从消费者的角度来看,两条链都源于同样的承诺并不是显而易见的。

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

答案 1 :(得分: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);