首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >级联jQuery.Deferred

级联jQuery.Deferred
EN

Stack Overflow用户
提问于 2016-12-07 17:19:03
回答 1查看 459关注 0票数 0

不是一个“反模式”:--这不是常见的“反模式”,可以通过直接返回嵌套延迟对象来解决.这个摘录是嵌套加载的代码的严重简化,它将在不久的将来返回Deferred,因此不可能直接从原始方法返回尚未存在的Deferreds。

此外,从原始(顶级)方法返回的延迟依赖于在不久的将来创建的多个Deferreds,其中只有“拒绝”被立即回传。

我发现自己最近经常写这样的东西:

代码语言:javascript
运行
复制
My.prototype.init=function() {
    var $dfd = $.Deferred();

    this.initSomethingElse() // returns Deferred
        .done(function() {
            $dfd.resolve();
        })
        .fail(function() {
            $dfd.reject();
        });

    return $dfd;
}

我编写了一个简短的函数来添加.link()方法来简化它,如下所示:

代码语言:javascript
运行
复制
My.prototype.init=function() {
    var $dfd = $.Deferred();

    this.initSomethingElse() // returns $.Deferred(addLinkMethodFce)
        .link($dfd);

    return $dfd;
}

但我认为这可能太普遍了,所以其他人可能会想到,我可能错过了jQuery中的一些开箱即用的解决方案。

问题:如果链接对象被解析/拒绝,当前的延迟推断将以同样的方式被解析/拒绝,jQuery能否将现有的延迟对象与其他延迟对象联系起来?

简单地说,就像dfd1Promise = $.when(dfd2)一样,除了不需要创建新的承诺,而只是简单地将现有的对象“链接”在一起,而不创建新的对象dfd1.link(dfd2)

谢谢。

EDIT#1:,当我看到很多问题的答案时,我还没有问--比如“我应该使用延迟推断吗?”我想澄清一下情况。

我有异步加载的代码(My.prototype.init确实加载异步脚本和数据,从而使其返回给调用方)。

而且,该代码还依赖于异步第三方代码- API不能修改- initSomethingElse(),该代码也将在不久的将来被解析并返回延迟。

关键是,如果该代码被拒绝,我的代码必须被拒绝。我希望有一些神奇的标准糖语法来重复$theirDfd.reject(function() {$myDfd.reject.call(...);});,仅此而已。

简单地说,是否有一种标准的方式来执行我的$myDfd.link($theirDfd);**?** ()

我只是大大简化了情况,用几行文字来表达,所以不要被骗以为我可能不需要延期,或者其他我没有问过的东西……

EDIT#2:为了进一步澄清.link()做了什么,下面是我目前使用的助手代码:

代码语言:javascript
运行
复制
/**
 * Adds some syntax sugar methods to Deferred object.
 *
 *   Deferred.link(dfd, ...) - if this object resolves/rejects/progresses it will resolve/reject/progress linked object as well
 *   Deferred.linkResolve(dfd, ...) - if this object resolves it will resolve linked object as well
 *   Deferred.linkReject(dfd, ...) - if this object rejects it will reject linked object as well
 *   Deferred.linkProgress(dfd, ...) - if this object progresss it will progress linked object as well
 *
 * Methods can be appended to Deferred object by two ways:
 *
 * $dfd = edfd($.Deferred());
 * $dfd = $.Deferred(edfd);
 *
 * @access public
 * @return {Deferred}
 */
function edfd($dfd) {

    /**
     * Helper used by this.link(), this.linkReject(), this.linkProgress(), this.linkResolve()
     *
     * @access private
     * @param {Boolean} accept link this Deferred's accept call to target's accept
     * @param {Boolean} reject link this Deferred's reject call to target's reject
     * @param {Boolean} progress link this Deferred's progress call to target's progress
     * @param {Object} targets array of Deferreds or array of arrays of Deferreds
     * @return {Deferred} this (called in $dfd context)
     */
    function linker(accept, reject, progress, targets) {
        targets = dna.core.getOpts(targets, [['dfdList', 'object'], 'recursive']);

        for (var i = 0; i < targets.dfdList.length; i++) {
            var $link = targets.dfdList[i];
            $dfd.then(
                accept && function() {$link.resolve.apply($link, arguments);},
                reject && function() {$link.reject.apply($link, arguments);},
                progress && function() {$link.progress.apply($link, arguments);}
            );
        }

        return this;
    }

    /**
     * If link this Deferred's rejection/resolution/progress to all linked Deferreds.
     *
     * @access public
     * @param {...Deferred} dfd jQuery Deferred objects or arrays of Deferred objects.
     * @return {Deferred} this object
     */
    $dfd.link = function() {
        return linker(true, true, true, arguments);
    };

    /**
     * If this Deferred is resolved then resolve also linked Deferreds.
     *
     * @access public
     * @param {...Deferred} dfd jQuery Deferred objects or arrays of Deferred objects.
     * @return {Deferred} this object
     */
    $dfd.linkResolve = function() {
        return linker(true, false, false, arguments);
    };

    /**
     * If this Deferred gets rejected then reject also linked Deferreds.
     *
     * @access public
     * @param {...Deferred} dfd jQuery Deferred objects or arrays of Deferred objects.
     * @return {Deferred} this object
     */
    $dfd.linkReject = function() {
        return linker(false, true, false, arguments);
    };

    /**
     * If this Deferred progresses then progress also linked Deferreds.
     *
     * @access public
     * @param {...Deferred} dfd jQuery Deferred objects or arrays of Deferred objects.
     * @return {Deferred} this object
     */
    $dfd.linkProgress = function() {
        return linker(false, false, true, arguments);
    };

    return $dfd;
}

EDIT#3:只供那些渴望看到特定用途的人使用。对象的延迟是像这个this.$dfd = $.Deferred(edfd);一样初始化的(参见我对上面这个问题的解决方案- function edfd(...) )

代码语言:javascript
运行
复制
/**
 * Public interface as required for payment processors.
 *
 * @access public
 * @param {Object} payData
 * @return {Deferred} resolved/rejected based on payment result.
 */
Braintree.prototype.process = function(payData) {
    this.cleanUp();
    this.payData = payData;
    this.createLayer();
    this.initBraintree(payData.clientToken)
        .linkReject(this.$dfd);

    return this.$dfd;
};
EN

回答 1

Stack Overflow用户

发布于 2016-12-07 18:06:32

TL;博士

问题:如果链接对象被解析/拒绝,当前的延迟推断将以同样的方式被解析/拒绝,jQuery能否将现有的延迟对象与其他延迟对象联系起来?

我知道您在想什么以及为什么;然而,ES2015已经用承诺链解决了这个问题。很好的例子:Promise.all() (MDN链路)是这种功能的一个很酷的实现(参见:“快速失败”)。

如果需要,可以使用多个延迟的,并使用jQuery.when()将它们“链接”在一起

代码语言:javascript
运行
复制
var d1 = $.Deferred();
var d2 = $.Deferred();

$.when( d1, d2 ).done(function ( v1, v2 ) {
    console.log( v1 ); // "Fish"
    console.log( v2 ); // "Pizza"
});

d1.resolve( "Fish" );
d2.resolve( "Pizza" );

(代码:https://api.jquery.com/jquery.when/)

阅读本很好的答案关于您的问题(及其相关链接)。答案为什么会对你的情况有帮助,这可能还不清楚,但是给它考虑并编写一些示例代码,你就会更好地理解。

正如其他人提到的那样:

  • 如果可能的话,你想避免 deferred's。
  • 使用.then()链接您的承诺(最后是.catch() )
票数 -1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/41023558

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档