【问题标题】:A bit confused with promises/chained functions in javascript与 javascript 中的 promises/chained 函数有点混淆
【发布时间】:2014-02-27 13:16:27
【问题描述】:

我仍在努力理解这一切,但显然我错过了一些基本概念。

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

虽然我称自己的函数不是异步的,但它们确实包含 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 :Promise" 甚至在承诺被激活之前。

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

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”以使其异步?

【问题讨论】:

  • 您的genericCalc 函数没有返回任何内容。所以它在fnArray中永远是未定义的;

标签: javascript jquery ajax asynchronous promise


【解决方案1】:

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

你需要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

这是个坏主意。您不应使用在某个时候设置的全局变量,而应仅将 Promise 用于传播更改,但 Promise 应表示这些值。这会带来更好的函数式编程风格。

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

【讨论】:

  • 好的,我正在努力解决这个问题......所以在调用 genericCalc 函数的代码中,我是否需要有类似 var myVar = genericCalc(params...) 的内容,或者该值如何返回?我不明白你的台词,“它将用该值解决结果承诺”对不起......(顺便说一下,可观察对象是由 Breezejs 创建的实体对象,我没有手动设置很多可观察对象)
  • 您可以访问then回调中的值:genericCalc(params).then(function(articleResults){…})。而不是手动.resolve() 延迟,它足以return 来自then 回调的值在下一个回调中访问它。您的轻量级基础设施可能需要可观察对象,因此您可能不会完全忽略它们(但是,我对它们知之甚少)。我的观点是,您不应该使用全局结构在一个过程中存储值并从下一个过程中访问它们,而是应该[仅]通过 promise 解析值传递结果。
  • 我没听懂,抱歉。这与我的传统 .net 知识相去甚远,所以它是一个谜。是否有在线资源您可以指出我,这将帮助我获得更好的基本理解,您认为好吗?当我看的时候,我似乎永远找不到任何相关的例子。
  • 我刚刚找到github.com/kriskowal/q/wiki/General-Promise-Resources,这似乎是一个很好的开始。如果他们还没有在那个列表中,我会把“博客文章”部分的两个顶级条目链接起来:-)
猜你喜欢
  • 1970-01-01
  • 2020-12-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-06-03
相关资源
最近更新 更多