【问题标题】:javascript function call timingjavascript函数调用时间
【发布时间】:2017-03-28 23:02:14
【问题描述】:

我正在尝试实现一个 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]);
    }
  });
}

【问题讨论】:

  • search.locatesearch.similar 返回什么类型的值?这些方法是异步的吗?
  • 不要使用push,而是分配给您存储在properly scoped 变量中的相应索引。
  • @RobG 假设它们是某种对象
  • @Bergi,你的意思是这样的 > all_results[i] = [res1,res2]
  • 如果它们是对象,那么您可能会将引用分配给同一个对象。但看起来(来自其他 cmets)调用可能是异步的,并且闭包会影响结果。

标签: javascript arrays callback


【解决方案1】:

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

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

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);
}

我封装了这两个调用以使其保持模块化,但由于“item”在闭包中,因此您实际上只需要 searchLocate() 函数来包装您在迭代期间捕获的项目引用。

【讨论】:

  • 是的,此代码仍然存在问题要求解决的排序问题。
  • 不确定“您在热门搜索中的参考资料”是什么意思?
  • "Javascript 是异步的"——不是一般的。
  • 唉,这是真的,问题仍然存在。两个异步调用都需要包装,因为 myList[i] 也没有参数化。我已经修复了我的示例。
  • @RobG stackoverflow.com/questions/2035645/… 我仍然认为它是异步的——因为在浏览器中事情是由事件触发的,而在 node.js 中仍然有一个事件循环。正如chattrat423 所发现的那样,将事物视为同步会让人陷入困境。但它肯定是单线程的,所以必须考虑长时间运行的循环等。
【解决方案2】:

这是一个很好的 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 讨论 Promises。以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
        });
    });
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-08-07
    • 1970-01-01
    • 2011-07-06
    • 1970-01-01
    • 2011-04-12
    • 1970-01-01
    相关资源
    最近更新 更多