有点混淆javascript中的promises / chained函数

时间:2014-02-27 13:16:28

标签: javascript jquery ajax asynchronous promise

我仍然试图解决所有这些,我显然缺少一些基本概念。

在我的代码中,我有一个场景,我希望连续调用几个函数,当它们全部完成时,用一个完成例程将其包装起来,计算小计并更新饼图。

虽然我自己调用的函数不是异步的,但它们确实包含了ajax调用,因此我想在计算总数并更新图表之前等待所有函数完成。

所以我尝试了:

    var fnArray= [];
    fnArray.push(genericCalc("use_", true, false, false));
    fnArray.push(doArticleImpacts(false));
    fnArray.push(genericProjectCalc("tpD2C_", false, false));
    fnArray.push(genericCalc("eol_", true, false, false));
    fnArray.push(calcPackaging(false));

    var calcPromise = Q.all(fnArray);

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

    function calcsDone() {
        calcTotals(); 
        setChart(selectedRow());
    }

    function calcsFailed() {
        logger.logError("Failure in calculations", "", null, true);
    }

...但是使用上面的代码并使用脚本调试器并在“return calcPromise”行上停止,fnArray设置为“0:undefined,1:undefined,2:Object,3:undefined,4 :承诺“甚至在承诺被激活之前。”

我知道这显然与我的功能有关,但我真的不明白我需要做些什么不同的事情。这些功能略有不同,但基本上类似于:

var genericCalc = function (calcPrefix) {
    var res_Array = ko.observable(); //holds returned results
    prjArticleArray.forEach(function (thisArticle) {

        var calcPromise = calcEOL(res_Array, thisArticle);  //another function containing async ajax call

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

        function calcsDone() {
            //do calculation subtotals here and set a knockout observable value
        }

        function calcsFailed() {
            logger.logError("Failure in " + calcPrefix + "calculation", "", null, true);
        }

    });
};

是什么让我的数组中的某些函数“未定义”,某些“对象”和某些“承诺”我想用于Q.all?我必须在我正在调用的函数的“calcsDone”部分中使用“Q.resolve”吗?

我已经在类似的行上看到了stackoverflow上的其他问题/答案,但它们似乎总是直接调用异步调用而我的第一级函数我在承诺中堆积起来不...我不应该将此结构用于非异步调用或只是将“setTimeout”添加到我的函数调用中以使它们异步?

1 个答案:

答案 0 :(得分:2)

  

我明白这显然与我的功能有关,但我真的不明白我需要做些什么不同

您需要return来自他们的承诺。您当前的genericCalc函数甚至不包含return语句(其中只包含forEach回调函数),因此它返回undefined

如果您需要等待每篇文章的结果,请使用Q.all,就像您已使用fnArray(实际上是promiseArray)一样。在genericCalc中,它应该如下所示:

var genericCalc = function (calcPrefix) {
    return Q.all(prjArticleArray.map(function (thisArticle) {
        var calcPromise = calcEOL(res_Array, thisArticle);  //another function containing async ajax call
        var result = calcPromise
                .then(calcsDone)
                .fail(calcsFailed);
        return result;
        …
    });
};
var res_Array = ko.observable(); //holds returned results
…
//do calculation subtotals here and set a knockout observable value

这是一个坏主意。您不应该使用在某些情况下设置的全局变量,并仅使用promises来传播更改,但承诺应该表示这些值。这导致了更好的功能性编程风格。

因此,不是设置全局变量,而是return来自calcsDone函数的结果,它将使用该值解析result承诺。