javascript函数调用时序

时间:2017-03-28 23:02:15

标签: javascript arrays callback

我正在尝试实现一个遍历列表的for循环,然后只有在找到第一个函数结果时调用两个函数。

问题是第二个函数(search.similar)可能需要更长时间才能获取结果。

使用下面的代码,当我运行时,(search.locate)的所有适当输出都是正确的,但只有myList的最后一个元素的结果存储在(search.similar)函数中。

即。 all_results = [[cat_res1,mouse_res2],[dog_res1,mouse_res2],[mouse_res1,mouse_res2]]

如何解决此问题,以正确的顺序附加正确的结果?

即。 all_results = [[cat_res1,cat_res2],[dog_res1,dog_res2],[mouse_res1,mouse_res2]]

var search = require('./search');
var myList = ['cat','dog','mouse'];
var all_results = [];
for (i=0; i<myList.length; i++){
  /* locate function*/
  search.locate(myList[i], function (err, searchResult){
    if (err){
      console.log("Error");
      return;
    }

    if (!searchResult){
      console.log("Cannot find it");
      return;
    }

    /*similarity function*/
    /* seems to take longer*/
    search.similar(myList[i], function (err, similarResult){
      if (err){
        return;
      }

      if (!similarResult){
        return;
      }

      var res1 = searchResult.data;
      var res2 = similarResult.data;
      /* append results to array*/
      all_results.push([res1,res2]);
    }
  });
}

2 个答案:

答案 0 :(得分:0)

Javascript可以被认为是异步的,因为特定函数的执行不一定同步发生,然而将JavaScript描述为异步可能会产生误导。更准确地说,JavaScript是同步的,并且具有各种回调机制的单线程&#34;

为了实现您的目标,尽管您可能仍然会遇到顶部数组的一些排序问题,但您需要将.similar()调用包装在另一个带有两个参数的函数中。您对&#34;项目&#34;的引用在顶部搜索正在改变:

function searchNestedSimilar(item, topRes) {
    search.similar(item, function (err, similarResult) {

        if (err){
            return;
        }
        if (!topRes){
            return;
        }

        var res1 = topRes.data
        var res2 = similarResult.data

        // append results to array
        all_results.push([res1,res2])

    }
} 

function searchLocate(item) {
   search.locate(item, function (err, searchResult) {

    if (err){
        console.log("Error");
        return;
    }
    if (!searchResult){
        console.log("Cannot find it");
        return;
    }
    searchNestedSimilar(item, searchResults);
}

我封装了两个调用以保持模块化,但是因为&#34; item&#34;在闭包中,你真的只需要searchLocate()函数来包装你在迭代过程中捕获你的项目引用。

答案 1 :(得分:0)

这是Promises的一个很好的例子(参见Bluebird JS,例如http://bluebirdjs.com/docs/getting-started.html)或者你可以用  async.map()。

这个页面也很好地讨论了它。 http://promise-nuggets.github.io/articles/14-map-in-parallel.html

还有很多Stack Overflow讨论Promise。例如Understanding JS Promises

如何使用Promise编写此代码的粗略示例:

var search = require('./search');
var myList = ['cat','dog','mouse']
var all_results = []
var Promise = require('bluebird');
var locate = Promise.promisify(search.locate);
var similar = Promise.promisify(search.similar);

for (i = 0; i < myList.length; i++){
    // locate function
    locate(myList[i], function (err, searchResult) {
        if (err) {
            console.log("Error");
            return;
        }
        if (!searchResult){
            console.log("Cannot find it");
            return;
        }
    }).then(function(result) {
        //similarity function
        similar(myList[i], function (err, similarResult) {
            if (err){
                return;
            }
            if (!similarResult){
                return;
            }

            var res1 = searchResult.data
            var res2 = similarResult.data

            // append results to array
            all_results.push([res1,res2])
        }).finally(function() {
            // NOP
        });
    });
}