javascript - Node.js 在回调中调用回调函数

标签 javascript node.js callback

我最近通过阅读《Node JS in Action》一书开始学习node.js。这可能是一个新手问题,但是在阅读了几篇关于回调函数和 javascript 变量范围的文章之后,我仍然无法理解本书第 5 章中这段代码背后的想法。

function loadOrInitializeTaskArray(file, cb) {
  fs.exists(file, function(exists) {
    var tasks = [];
    if (exists) {
      fs.readFile(file, 'utf8', function(err, data) {
        if (err) throw err;
        var data = data.toString();
        var tasks = JSON.parse(data || '[]');
        cb(tasks);
      });
    } else {
      cb([]); 
    }
  });
}

function listTasks(file) {
  loadOrInitializeTaskArray(file, function(tasks) {
    for(var i in tasks) {
      console.log(tasks[i]);
    }
  });
}

它包括三个回调函数,分为两个函数。首先调用 listTasks(..) ,然后调用 loadorInitializeTaskArray(.. ) 。我的问题从这里开始,这个调用是如何由 Node 处理的? loadOrInitializeTaskArray 有两个参数,第二个是回调函数,根据签名,它不应该接受任何参数,但它确实接受!!
cb(..) 何时在 loadorInitializeTaskArray 中被调用,那是什么(与调用辅助函数的函数相同)?

“tasks”是在函数loadOrInitializeTaskArray中声明的数组,我们如何在listTasks(..)函数中访问它?

我知道在 Javascript 中,变量的作用域是在它定义的函数和所有嵌套函数内部。但我在这里很难理解它。那么有人可以解释一下这是怎么回事吗? 谢谢

最佳答案

您确实很难理解嵌套函数内变量的范围。那么,让我们开始吧。
让我们考虑一下这段代码

function foo(){
  var a = 3;
  function bar(){
    console.log(a);
  }
  return bar;
}
var baz = foo();
baz(); // the value of a i.e 3 will appear on console

如果您了解 C、C++ 等语言...您的大脑会像这样解释此代码。如果您不知道其中任何一个,请忽略这些要点。

  • foo()被调用时,变量a将被声明并赋值3。
  • foo返回时,包含a的堆栈将被销毁。因此 a 也会被销毁。
  • 那么 baz() 究竟是如何输出 3 的。 ???

嗯,在 javascript 中,当调用一个函数时,发生的事情与在 C 中不同。因此,在进一步阅读之前,首先让所有 C 事情从你的脑海中消失。

在 JavaScript 中,作用域解析是通过沿着一系列对象链向下移动来完成的,这些对象定义了该代码“作用域内”的变量。让我们看看如何?

  • 当您声明全局 JavaScript 变量时,您实际上所做的是定义全局对象的属性。
  • 在顶级 JavaScript 代码(即不包含在任何函数定义中的代码)中,作用域链由单个对象(全局对象)组成。
  • 在非嵌套函数中,作用域链由两个对象组成。第一个是定义函数参数和局部变量的对象,第二个是全局对象。
  • 在嵌套函数中,作用域链具有三个或更多对象。当定义一个函数时,它会存储当时有效的作用域链。当调用该函数时,它会创建一个新对象来存储其局部变量,并将该新对象添加到存储的作用域链中,以创建一个新的、更长的链来表示该函数调用的作用域。

所以,当执行 foo() 时。它创建一个新对象来存储其局部变量。因此,变量 a 将存储在该对象中。并且,还定义了 bar。当 bar 被定义时,它存储有效的作用域链。因此, bar 的作用域链现在包含具有变量 a 的对象。因此,当返回 bar 时,它会引用其作用域链。因此它知道a

所以,我想它回答了你的问题 Node 如何处理代码。

你写道:

loadOrInitializeTaskArray takes two arguments and the second one is the callback function which shouldn't accept any parameters according to is signature but it does!!

回调函数为

function(tasks) {
    for(var i in tasks) {
      console.log(tasks[i]);
    }
}

它接受一个参数tasks。所以,你错了。

loadOrIntializeTaskArray被调用时,cb指的是这个回调函数。 cb(arg) 基本上执行此 tasks = arg 操作,其中tasks 是回调函数中的参数。

我想您仍然会有很多问题。请在评论中告诉我。我强烈建议您在深入了解 Node 之前先浏览一下 Core Javascript。

关于javascript - Node.js 在回调中调用回调函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27393206/

相关文章:

javascript - JavaScript 对象构造函数的问题,其中参数是其他对象

javascript - jQuery 点击事件目标填充

javascript - 在 Flask/Javascript 中获取动态列表元素到服务器

javascript - Socket.io:如何让每个人获得不同的 channel ?

event-handling - Node.js 重复监听器问题

javascript - 在 JavaScript vb.net 中为 HiddenField 设置新值

javascript - 创建 Node.js + socket.io 服务器/客户端,进行用户身份验证、发送/接收数据

node.js - NodeJS 请求库如何获取完整的 URL,包括 URI 和查询字符串参数

javascript - 异步循环中的 Node.js Api 调用

javascript - DOM 事件在事件队列中的优先级