繁体   English   中英

重复使用不止一次

[英]Reuse Deferred more than once

我正在使用延迟,因为我需要异步执行多个进程。

更清楚的是,这是我治疗的意义:

  • 处理1:调用提供用户权限的ajax服务
  • 处理2:调用提供链接和标签的ajax服务。

我需要同时调用这两个服务,然后获得两个服务的统一响应,以便根据权限显示链接(我的真正问题是第三个ajax服务,但让我们谈论只有2个来简化)。

首先,我将deferred声明为全局变量:

var treatment1 = $.Deferred();
var treatment2 = $.Deferred();

然后,当我需要完成这项工作时,我将解决方法调用所需的数据,以便在全局唯一处理中使用它:

  • 当我的第一个ajax服务响应: treatment1.resolve(responseData1)
  • 当我的第二个ajax服务响应: treatment2.resolve(responseData2)

当treatment1和2完成时,会触发done事件:

$.when(treatment1, treatment2).done(function(responseData1,responseData2) {
    DoGlobalTreatmentWithAllResponseData(responseData1,responseData2)
}

我的问题是延期只工作一次。

由于我的网站主要是在ajax中实现的,我需要多次激活该事件。

用户可以单击按钮来搜索用户。 然后显示用户列表,并且异步调用ajax服务。 该操作可以无限重复。

我只需要一种方法来重用延迟但多次的原则。 我知道这个问题已经讨论过了,每个人都说deferred不能这样工作。

但是,是否真的无法重置延迟状态或重置承诺(即使通过使用AOP或其他方式实现自定义解决方案)?

如果不可能,我可以使用什么解决方案? 我不想一个接一个地开火治疗,但我真的想在完成所有治疗后做全局治疗(也就是说,活动中的最后一次治疗结束后),我想使用每个治疗的responseData服务。

这是我想要自定义的示例代码: http//jsfiddle.net/PLce6/14/

我希望明确,因为英语不是我的母语。

预先感谢您的帮助。

延迟只能被解决/拒绝一次......但是,我认为问题在于你是如何构建代码的...

只要你每次初始化你的延期,这样做没有任何问题...我认为问题是这样的:

首先,我将deferred声明为全局变量:

 var treatment1 =$.Deferred(); var treatment2 = $.Deferred(); 

相反,您可以尝试在按钮单击中调用的函数中执行此操作

用户可以使用按钮来搜索用户

所以有这样的功能:

function onClick() {
    var treatment1 =$.ajax({url: '/call1'}); 
    var treatment2 = $.ajax({url: '/call2'});
    $.when(treatment1, treatment2).done(function(obj1, obj2) {
            // do whatever else you need
    });
}

现在,从您的帖子的其余部分看起来,您正在尝试重用延迟 - 但在这种情况下,您的原始解决方案应该没有将deffered保持为全局的问题,因为您的完成将使用他们解决的任何数据调用。

你可以发布一些代码来帮助解释你正在尝试做什么。

从我自己的评论中更新以进行详细说明

基于op的小提琴,他希望能够多次触发依赖动作。 解决方案是让依赖操作创建新的延迟并将$.when到自身。 请参阅http://jsfiddle.net/PLce6/15/上的更新小提琴

// global
var d1 = $.Deferred();
var d2 = $.Deferred();
var d3 = $.Deferred();

// here's the reset 
function resetDeferreds() {
d1 = $.Deferred();
d2 = $.Deferred();
d3 = $.Deferred();
$.when(d1, d2, d3).done(
    function (responseData1, responseData2, responseData3) {
       DoGlobalTreatmentWithAllResponseData(responseData1, responseData2, responseData3);
    resetDeferreds();
});

// the onclick handlers
function do3() {
d3.resolve('do3 ');
return d3;
}

// the top level $.when
$.when(d1, d2, d3).done(function (responseData1, responseData2, responseData3) {
    DoGlobalTreatmentWithAllResponseData(responseData1, responseData2, responseData3);
    resetDeferreds();
});

也许你的代码设计得不好?

我不明白这是怎么回事。 异步过程应该负责每次都创建一个新的Deferred对象。

function doSomething() {
    var d = $.Deferred();

    setTimeout(function () {
        d.resolve();
    }, 1000);

    return d;
}

function doSomethingElse() {
    var d = $.Deferred();

    setTimeout(function () {
        d.resolve();
    }, 1000);

    return d;
}

然后您可以随时执行以下操作:

$.when(doSomething(), doSomethingElse()).done(function () {
    console.log('done');
});

总有一个解决方案:

如果你绝对需要能够在同一个Deferred上多次调用resolve ,那么你应该将Deferred包装到另一个对象中,让我们说DeferredWrapper ,它将公开与Deferred相同的API但是会将所有方法调用委托给它的封装Deferred

除了委托函数调用之外, DeferredWrapper还必须跟踪在对象上进行的所有侦听操作(例如,完成,始终,失败...)。 DeferredWrapper可以将所有操作作为[functionName,arguments]元组存储在内部this._actions属性中。

最后,您需要为状态更改操作(例如,reject,resolve,resolveWith ...等)提供一个特殊的实现,如下所示:

  1. dthis._deferred引用的内部Deferred

  2. fn是被调用函数的函数名。

  3. 如果d.state()挂起

    3.1 do d = this._deferred = [[native jQuery Deferred]]

    3.2在d上应用所有操作。

  4. 返回d[fn].apply(d, arguments)

注意:您还需要实现自定义promise实现,并确保其行为正确。 您可以使用类似于所描述的方法。

我要建议一个小小的改变。 您不清楚的一个因素是每次治疗1和治疗2的结果是否不同。 如果他们那么做@raghu和@ juan-garcia

function onClick() {
    var treatment1 =$.ajax({url: '/call1'}); 
    var treatment2 = $.ajax({url: '/call2'});
    $.when(treatment1, treatment2).done(function(obj1, obj2) {
            // do whatever else you need
    });
}

如果他们没有改变,那么这样做:

var treatment1 =$.ajax({url: '/call1'}); 
var treatment2 = $.ajax({url: '/call2'});

function onClick() {
    $.when(treatment1, treatment2).done(function(obj1, obj2) {
            // do whatever else you need
    });
}

或者一些变化。 因为一旦完成,您的回调函数将始终立即执行。 它仍然是异步的,但它不需要等待,因为一切准备就绪。 这适用于两种用例。 这是一种非常常见的数据模式,在页面中绘制新组件时,在功能上非常有用之前可能需要几秒钟才能加载。 这是一个非常有用的延迟加载机制。 一旦它进入,虽然一切看起来好像它瞬间响应。

我在JSFiddle的示例中重新编写了javascript,以显示我认为您需要查看的基础知识。 在这里 举个例子,我认为错误在于相信必须多次调用resolve才能触发行为。 调用完成行为会提示一次性行为,并且每次完成调用都会将新行为加载到队列中。 Resolve被称为一次。 $ .when()。done()你可以调用多次,因为你的行为依赖于特定的when()条件。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM