【问题标题】:How can I specify the order in which node.js functions are evaluated?如何指定评估 node.js 函数的顺序?
【发布时间】:2012-09-14 11:01:13
【问题描述】:

下面,我尝试在console.log(toObtain) 之前评估im.identify,但似乎console.log(toObtain)im.identify 之后被调用。如何确保函数按照我希望它们被调用的顺序被调用?

var toObtain; //I'm trying to set the value of this variable to features (inside the callback).

var im = require('imagemagick');
im.identify('kittens.png', function(err, features){
  if (err) throw err
  //console.log(features);
  toObtain = features;
  console.log(toObtain); //this prints { format: 'PNG', width: 400, height: 300, depth: 8 }
})

console.log(toObtain); //This function call is evaluated BEFORE im.identify, which is exactly the opposite of what I wanted to do.

【问题讨论】:

标签: node.js


【解决方案1】:

异步意味着事情在准备就绪时发生(彼此之间没有任何同步关系。)

这意味着如果您希望打印或以其他方式对异步函数中创建的值进行操作,则必须在其回调中执行此操作,因为这是保证该值可用的唯一地方。

如果您希望订购多个活动,以便它们一个接一个地发生,您需要应用以同步方式(一个接一个)“链接”异步函数的各种技术之一,例如 async javascript曹兰写的图书馆。

在您的示例中使用异步,您将:

var async=require('async');

var toObtain;

async.series([

  function(next){ // step one - call the function that sets toObtain

    im.identify('kittens.png', function(err, features){
      if (err) throw err;
      toObtain = features;
      next(); // invoke the callback provided by async
    });

  },

  function(next){ // step two - display it
    console.log('the value of toObtain is: %s',toObtain.toString());
  }
]);

之所以如此,是因为异步库提供了一个特殊的回调,用于移动到系列中的下一个函数,该函数必须在当前操作完成时调用。

请参阅async 文档了解更多信息,包括如何通过 next() 回调将值传递给系列中的下一个函数以及作为 async.series() 函数的结果。

可以使用以下方法将异步安装到您的应用程序中:

npm install async

或全局,因此它可用于您的所有 nodejs 应用程序,使用:

npm install -g async

【讨论】:

  • 虽然异步模块是流行的库,但我想你会同意,当你还在学习的时候,最好不要使用其他库。如果它具有显着优势,以后一定要使用它。
  • @saeed 恐怕我不能同意你的看法。围绕异步“事件驱动”编程进行思考是困难的,因为我们都倾向于从因果关系的角度来思考,其中一件事“导致”另一件事,而事件驱动编程往往会掩盖编程操作之间的因果关系。跨度>
  • 话虽如此,如果您对“滚动自己的”库以按顺序运行异步函数感兴趣,您可以查看我的 github 沙箱中的“runner”。 (github.com/raisch/sandbox/tree/master/runner)
  • @RobRaisch 这个库有文档吗?我想知道如何使用这个库以特定顺序评估同步函数,但我找不到“readme.md”或“readme.txt”。
  • @RobRaisch 当我尝试运行上面的示例时,我在终端中收到以下错误:ReferenceError: im is not defined
【解决方案2】:

这就是节点的工作方式。这是正常的异步行为。

为了避免在使用节点时发疯,将事物分解为每个都有特定目的的函数很重要。每个函数都会根据需要调用下一个传递参数。

var im = require('imagemagick');

var identify = function () {

      im.identify('kittens.png', function(err, features){

         doSomething(features) // call doSomething function passing features a parameter.

      })

}(); // this is the first function so it should self-execute.

var doSomething = function (features) {

       var toObtain = features;

       console.log(toObtain) //or whatever you want to do with toObtain variable
};

【讨论】:

  • 仍然,是否可以让异步函数按特定顺序执行?
【解决方案3】:

这是正常的,因为 im.identify 接缝是异步的(它需要回调)。因此,回调可以在下一行之后执行。

编辑:因此,您必须在toObtain = features;

之后放置用户获取IN您的回调的任何代码

【讨论】:

  • 是否可以在回调之外获取toObtain的值?我正在尝试编写一个实际返回 toObtain 值的函数,以便它可以在回调之外使用。
  • 是否可以在脚本的最后一行(在回调之外)之前评估回调?
  • 不,这就是异步的本质(在本例中为 node.js)。你必须改变你的思维方式。在这种情况下,如果您对结果(特征)有一些事情要做,并且如果您想封装行为,您可以创建一个以函数作为参数的函数,并在 im.identify 中执行它回调,将你想要的数据传递给它。
猜你喜欢
  • 2018-11-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-01-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多