JS函数的串行调用

Posted

技术标签:

【中文标题】JS函数的串行调用【英文标题】:Serial invocation of JS functions 【发布时间】:2014-08-24 02:35:07 【问题描述】:

这是我正在尝试做的(实际问题有所不同,但概述如下):

    我有一个数组 [A..Z]。

    对于上述数组中的每个字母,我有另一个数组:

    someArray[alphabet] = [1..100] //another array
    

    对于 someArray[alphabet] 中的每个数字,还有另一个数组:

    anotherArray[number] = [a..z,A..Z,1..1000]
    

假设对于每个 alphabet,我获取 someArray[alphabet],并且对于 someArray[alphabet] 中的每个 number /strong>,我从服务器获取 anotherArray[number] - 这需要时间。

此外,获取它们的函数如下 - 我进行 jQuery post 调用以从服务器获取数据。我需要按顺序执行它们。

getAlphabets()

    //I get them here
    //For Each alpha, I call:
    getNumbers(alpha);

getNumbers(alpha)

    //I get someArray here.
    //For Each element in someArray
    //getAnotherArray(element)

getAnotherArray(number)

    //I get them here
    //For Each element in anotherArray
    //get all [a..z,A..Z,1..1000]
    //display them

问题是 getNumbers(alpha) 的迭代没有等待 getAnotherArray(previousIteration) 完成。执行(函数调用并行运行(A..Z 的同时执行)而不是其他方式。

我的步骤:

    我能够按预期检索所有数据,但不是按顺序检索。

    我尝试使用 flagssetInterval, clearInterval 来允许/禁止下一次迭代 - 它们没有按预期工作。

    我也尝试过使用类似 - getAlphabets() && getNumbers() & getAnotherArray() 之类的东西,以为会按顺序执行,但我错了。

    李>

【问题讨论】:

您是否必须对 3D 数组中的每个单元格进行单独的 ajax 调用,并且希望它们按顺序运行?这些数组是否已经存在并且您只想遍历它们为每个单元格进行 ajax 调用?还是在进行 ajax 调用时构建数组? 我正在使用 ajax 调用构建数组。首先,我得到字母列表。然后,对于每个字母表,我调用 getNumbers(),对于 getNumbers() 返回的数组中的每个数字,我调用 getAnotherArray() -> 它传递适当的参数,获取相应的元素并从中构建一个数组。我可以一次完成所有这些,但我需要它们是连续的。 【参考方案1】:

当您进行 ajax 调用等异步操作时,要按顺序迭代某些数据结构,您必须使用不同形式的迭代。您不能使用常规的 for 循环或 while 循环。相反,您创建一个函数来进行迭代。您创建一个状态变量来跟踪您在迭代中的位置。您启动了一个 Ajax 调用。当它返回时,您处理结果,然后启动下一个 ajax 调用(随时更新迭代状态)。

这是一个例子:

假设你有一个任意长度的数组:

var theData = [...];

而且,您希望对该数组中的每个项目进行 ajax 调用,并将结果收集到另一个数组中。出于特定原因,您希望强制 Ajax 调用按顺序进行,以便仅在第一次调用完成后进行第二次调用,依此类推。

function processArray(data) 
    var def = $.Deferred();
    var currentItem = 0;
    var results = [];

    function next() 
        if (currentItem < data.length) 
            $.ajax(...).done(function(result) 
                // process the result here
                results.push(result);
                // advance the counter and start the next Ajax call
                ++currentItem;
                next();
            ).fail(function(jqXHR, textStatus, errorThrown) 
                def.reject(jqXHR, textStatus, errorThrown);
            );
         else 
             def.resolve(results);
        
    
    next();
    return def.promise();


// call it like this
processArray(theData).done(function(results) 
    // do something with the results array here
);

现在,如果您有三个维度的迭代状态,那么跟踪状态会稍微复杂一些(您将拥有三个版本的 currentItem 来跟踪您在三个维度中的每一个维度中的位置),但它否则可能与完成一个维度时增加的复杂性相似的逻辑,您需要换行到下一行并重新开始。

【讨论】:

感谢您的更新。请给我一些时间来理解代码。【参考方案2】:

当您使用 ajax 来获取数据时,请求不会按顺序执行,因为 ajax 是一个异步函数。您需要关闭async。所以,它会按照你想要的顺序运行。

async: false

异步(默认:true)类型:布尔值 默认情况下,所有请求都是异步发送的(即默认设置为 true)。如果您需要同步请求,请将此选项设置为 false。跨域请求和 dataType: "jsonp" 请求不支持同步操作。请注意,同步请求可能会暂时锁定浏览器,从而在请求处于活动状态时禁用任何操作。

示例:

jQuery.ajax(
    url: strUrl,
    success: function(html) 
      strReturn = html;
    ,
    async:false
  );

【讨论】:

async: false 与ajax 调用一起使用绝不是一个好主意,因为它只会锁定浏览器。解决方案是以与异步调用一起使用的不同方式对迭代进行编码,而不是摆脱异步调用。

以上是关于JS函数的串行调用的主要内容,如果未能解决你的问题,请参考以下文章

JS async & await & 串行并行

Node.js-串行化流程控制

js 函数如何去调用另一个函数中的函数?

(js)使用new对函数进行构造调用

js函数带参调用

jsp页面中调用js函数