0

我创建了一个 web api 方法,该方法使用我发布到该方法的 json 对象执行计算。我的理解是 jquery 帖子是异步的?假设是这样,我希望能够将调用此 api 方法的 js 函数的多个调用链接在一起,因为某些调用是顺序关键的。

该异步 api 方法连续调用 80 次。我不想这样做:

asyncMethodCall1(myParams).then(asyncMethodCall2(myParams).then...)) 
...

因为没有必要像这样链接它们,因为它们都不依赖于另一个并且可以同时运行。但是最后我需要做一些其他的计算,这些计算取决于之前的结果已经完成。

有没有一种方法可以进行一组呼叫,然后是“then”?这仅仅是一个类似的情况:

mySynchronousFunction(params).then(function() {...do other calcs});

function mySynchronousFunction(params) {
    asyncmethodcall1(myparams);
    asyncmethodcall2(myparams);
    asyncmethodcall3(myparams);
    ...
    asyncmethodcall76(myparams);
}

还是我需要在某个地方有一个“setTimeOut”?JavaScript 是我正在尝试学习的东西,现在对我来说有点奇怪!

编辑 1

好吧,我很难过。

我知道这是导致问题的根本原因,但很难找到来自同步语言的人可以遵循和理解的基本介绍性内容。目前我正在处理的资源是这个资源,它似乎有一些意义,但它仍然没有陷入:http ://blog.mediumequalsmessage.com/promise-deferred-objects-in-javascript-pt1-theory-and -语义

目前我有这个:

        $.when(
            individualImpactCalc('byWeightAndFactor', 'CO2e', articleResults().material_CO2e),
            individualImpactCalc('byWeightAndFactor', 'Water', articleResults().material_Water),
            individualImpactCalc('byWeightAndFactor', 'pH', articleResults().material_pH),

        ...lots of other calls in here...

        ).then(function () {
            //do calculation totalling
            alert("I'm done!");
        }).fail(function() {
            alert("Argh! I failed!");
        });

...而且它根本无法按我的意愿工作。我从来没有收到警报显示。影响计算已完成,可观察值已更新,我的页面值更改,但没有警报。

我在这里根本缺少什么?

编辑 2

我根本缺少的是调试链式 Promise 的困难!一旦我修复了一个没有冒泡的隐藏参考错误,它实际上就可以工作了。大量通过 javascript 的艰苦步骤终于找到了它。

只是为了在答案组合中添加另一个元素,我使用了 Q 库,因为无论如何这都是在 Durandal/Breeze 中使用的,并且很容易保持代码的一致性。我用 $.when 试了一下,效果也很好。我用 Promise 进行了尝试,但由于“未定义 Promise”而失败。

我的工作Q实现:

        var calcPromise = Q.all([
            individualImpactCalc('byWeightAndFactor', 'CO2e', articleResults().material_CO2e),
            individualImpactCalc('byWeightAndFactor', 'Water', articleResults().material_Water),
            individualImpactCalc('byWeightAndFactor', 'pH', )]);

        return calcPromise
            .then(calcsDone)
            .fail(calcsFailed);

        function calcsDone() {
            alert("all calcs done");
        }
        function calcsFailed() {
            alert("Argh! Calc failure...");
        }
4

3 回答 3

1
于 2013-11-12T10:39:51.220 回答
1

正如其他人指出的那样,您可以使用$.when(...)一次调用所有方法,并且只有.then()在所有方法都完成后才继续。但这并不能解决您的问题,因为这些方法是一次性启动的,并且没有链接。对您的 web api 的调用仍然可以以随机顺序进入和完成。

尽管您的示例显示了不同的异步方法,但您的描述听起来就像您只有一种具有不同参数值的方法。那么为什么不将这些参数收集到一个数组中,然后将调用链接到一个循环中呢?

var params = [ 27, 38, 46, 83, 29, 22 ];

var promise = asyncmethodcall(params[0]);
for (var i=1; i<params.length; i++) {
    promise = promise.then(buildAsyncmethodcall(params[i]));
}

function buildAsyncmethodcall(param) {
    return function() {
        return asyncmethodcall(param);
    }
}

http://jsfiddle.net/qKS5e/ - 看看为什么我必须使用另一个函数构建函数

如果你真的想调用不同的方法,你可以编写一个 jQuery 插件,例如。$.whenSequential(...)向其中传递返回 Deferred 对象的函数数组,如下所示:

$.whenSequential( // your cool new plugin
    function() { return callasyncmethod1(123); },
    function() { return callasyncmethod2(345); },
    function() { return callasyncmethod3(678); }
);

插件方法就像上面的 for 循环一样工作,但不是 params,而是迭代函数参数并一一传递给then().

无论哪种方式,您都无法绕过以某种方式将所有调用包装在一个函数中以将它们链接起来,因为否则它们将立即执行(例如 with $.when)。

于 2013-11-12T12:02:01.140 回答
1

您正在寻找的是 jQuery when 方法: http ://api.jquery.com/jQuery.when/

在将多个 Deferred 对象传递给 jQuery.when 的情况下,该方法从一个新的“主” Deferred 对象返回 Promise,该对象跟踪它已传递的所有 Deferred 的聚合状态。该方法将在所有 Deferred 解析后立即解析其主 Deferred,或者在其中一个 Deferred 被拒绝时拒绝主 Deferred。

具体来说,您将不相互依赖的调用放在when中,将依赖它们的调用放在then中。

$.when(/* independent calls */).then(/* dependent calls */);

例如,如果你想并行运行延迟 1 和 2,然后运行 ​​3,然后运行 ​​4,你可以这样做:

$.when(def1, def2).then(def3).then(def4);
于 2013-11-12T10:38:58.803 回答