【问题标题】:$.Deferred.then() function doesn't allow unknown number of time to call the function dynamically?$.Deferred.then() 函数不允许未知次数动态调用该函数?
【发布时间】:2014-09-03 18:04:18
【问题描述】:

我在 Google 搜索 jQuery Deferred and Promise for sequential execution of synchronous and asynchronous funcitons 时发现了这个脚本。

这可以解决我按顺序执行脚本的问题。但是 then() 函数的问题是我无法知道我可以调用这个函数多少次。我可以调用函数 a() 3 次,下一次,我可以调用它 20 次,等等。所以,那不适用于 then()。 then() 函数不允许数组堆栈。那么,你们是如何让这个概念发挥作用的呢?

fucntion a(counter)
{
    $deferred = $.Deferred();

    //Run some scripts here...
    alert(counter);

    $deferred.resolve();
    return $deferred;
}
function Test()
{
    var d = $.Deferred(), 
    p=d.promise();
    p.then(a(0)).then(a(1)).then(a(2));
    d.resolve();
    return d;
}

Test().done(function(){ alert('done'); }).fail(function() { alert('fail'); });

【问题讨论】:

  • 您将a(N) 返回的$deferred 传递给.then()。相反,您需要传递一个回调函数,例如.then(a).
  • 我不知道您提到多次致电Test() 是什么意思?这有什么问题,当你做你没想到的事情时会发生什么? “允许数组堆栈”是什么意思?
  • 我更新了问题,我的意思是a(),而不是Test()...
  • 是的,你正在同时调用a(0); a(1); a(2);,这使得异步进程同时运行。
  • 那么问题是什么?你想“创造”什么概念?

标签: javascript jquery jquery-deferred


【解决方案1】:

我认为您要问的是如何链接和未知数量的电话。在这种情况下,您可以轻松循环并继续添加更多.then。例如:

for (var i=0; i < someLimit; i++) {
    p = p.then(a(i));
}

这将链接调用,以便它们一个接一个地被调用。如果您希望它们并行执行,那么 @jantimon 建议使用 .when 是可行的方法。

这是因为链接的工作原理。对.then 的调用会返回一个promise,以便您可以在返回的promise 上再次调用.then。见:http://api.jquery.com/deferred.then/

【讨论】:

  • 谢谢。是的,链接有未知数量的调用。我不知道这会起作用。
  • 我喜欢你的解决方案,但这也会并行执行它们,不是吗?
  • @jantimon: 否。.then 将在延迟解决时执行。所以他们会一个接一个地执行。不要与.when 混淆
  • @MattBurland: a(i) 不返回一个函数,而是一个承诺。它将并行执行它们,而不是等待任何东西……
  • @Bergi:啊,是的,我错过了那部分。但我不确定他们为什么首先返回延迟。
【解决方案2】:

您可以使用jQuery.when
请注意,这会同时执行多个异步操作:

jsFiddle Demo

给你a 函数,它返回一个异步承诺:

function a(counter, $target) {
    var $deferred = $.Deferred();
    setTimeout(function () {
        $target.text($target.text() + ' ' + counter);
        $deferred.resolve();
    }, 1000);
    return $deferred;
}

并行:

function Test1() {
    return $.when($.map([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], function (val, i) {
        return a(i, $('#test1'));
    }));
}

Test1().done(function () {
    $('#test1').css('font-weight', 'bold');
}).fail(function () {
    alert('fail');
});

要按顺序运行它,您需要一个 promiseLoop 助手:

function promiseLoop(arr, callback) {
    return arr.reduce(function (previousPromise, val, i) {
        return previousPromise.then(function (resultArray) {
            return $.when(callback(val, i)).then(function (res) {
                return resultArray.concat([res]);
            });
        });
    }, $.when([]));
}

function Test2() {
    return promiseLoop([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], function (val, i) {
        return a(i, $('#test2'));
    });
}


Test2().done(function () {
    $('#test2').css('font-weight', 'bold');
}).fail(function () {
    alert('fail');
});

【讨论】:

  • 谢谢。如果我需要在并行线程中运行它,我会保存这个脚本的副本。
  • 查看演示以了解并行或顺序运行的示例
  • 嗯...很好...谢谢。 :-)
猜你喜欢
  • 1970-01-01
  • 2013-02-16
  • 2014-10-05
  • 2015-03-13
  • 2021-08-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多