重复使用不止一次

时间:2013-11-14 16:27:18

标签: javascript jquery asynchronous jquery-deferred

我使用deferred,因为我需要异步执行多个进程。

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

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

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

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

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

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

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

当治疗1& 2完成,结束事件被触发:

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

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

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

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

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

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

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

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

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

提前感谢您的帮助。

3 个答案:

答案 0 :(得分:2)

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

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

  

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

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();
});

答案 1 :(得分:1)

也许您的代码设计不合理?

我不知道这会是一个什么问题。异步过程应该负责每次都创建一个新的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');
});

总有一个解决方案:

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

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

最后,您需要为状态更改操作(例如,拒绝,解析,解析等等)提供一个特殊的实现,如下所示:

  1. d 成为Deferred引用的内部this._deferred

  2. fn 成为被调用函数的函数名。

  3. 如果d.state()不是待处理

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

    3.2在d

  4. 上应用所有操作
  5. 返回d[fn].apply(d, arguments)

  6. 的结果

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

答案 2 :(得分:0)

我要建议一个小小的改变。您不清楚的一个因素是每次治疗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,以显示我认为您需要查看的基础知识。那是here。举个例子,我认为错误在于相信必须多次调用resolve才能触发行为。调用完成行为会提示一次性行为,并且每次完成调用都会将新行为加载到队列中。 Resolve被称为一次。 $ .when()。done()你会根据特定的when()条件调用多次行为。

相关问题