【问题标题】:JavaScript variables hoisting in nodejs/async在 nodejs/async 中提升 JavaScript 变量
【发布时间】:2013-06-07 14:33:49
【问题描述】:

在下一个示例中,我无法访问函数“fetcher”、“parser”和“saveToDb”中的变量“locals”

var parser = require('parser.js');
var fetcher = require('fetcher.js');
var saveToDb = require('models/model.js');
var async = require('async');


function task() {
    var locals = []    //<-- declared here
    async.series([
        fetcher,    //<--  can not access "locals"
        parser,     //<--  can not access "locals"
        saveToDb    //<--  can not access "locals"
    ],
            function (err) {
                if (err) return callback(err);
                callback(null);
    });
}

在下一个示例中,“本地”是可访问的。我只是从请求的模块中复制了函数声明,并将它们直接粘贴到“async.series”中。

var async = require('async');

function task() {
    var locals = []    //<-- declared here
    async.series([
        function(callback) {// <-- can access "locals"},  
        function(callback) {// <-- can access "locals"},
        function(callback) {// <-- can access "locals"}
    ],
            function (err) {
                if (err) return callback(err);
                callback(null);
    });
}

虽然这可行 - 我确实想保持我的代码模块化。 我该如何解决? 或者 - 我在这里忘记了 JavaScript 的基础知识

谢谢。

【问题讨论】:

  • 可以说您忘记了一件事:如果代码可以访问或多或少的随机变量(在本例中为@ 987654323@ 变量)在别处定义。使某些东西模块化通常不仅仅需要在文件周围传播东西,它还需要明确代码不同部分之间的关​​系,例如通过将函数需要的所有数据作为参数传递。

标签: javascript node.js scope async.js


【解决方案1】:

在第一个示例中,回调位于另一个范围内,因此无法访问 locals

您可以创建将locals 变量作为第一个参数传递的部分函数,​​但这需要您重写回调。

// creating a partial
async.series([
  fetcher.bind(fetcher, locals),
  parser.bind(parser, locals),
  saveToDb.bind(saveToDb, locals)
], ...)

// new function signatures
function fetcher (locals, callback) { ... }
function parser  (locals, callback) { ... }
function saveToDb(locals, callback) { ... }

【讨论】:

  • 为什么要绑定?我想这是因为我没有在我的特定回调中使用“this”——这并不重要——但我确实想了解你为什么添加绑定。谢谢罗伯特。
  • bind 有两个目的:确定函数中的 this 是什么,还可以创建具有“附加”到它们的预先指定参数的部分函数(参见 the MDN explanation 和 @ 987654322@演示原理)。
  • 我想我现在得到了这部分,但是即使“async.series”除了“回调”之外不接受任何参数,它还能工作吗?
  • 当然 :) 我更新了 my gist 以展示如何将它与 async 一起使用。
  • 我认为 fetcher.bind(fetcher, locals) 最好是 fetcher.bind(undefined, locals) 将原始函数指定为 this 的值对我来说看起来很奇怪。
【解决方案2】:

您可以像这样定义 3 个提到的函数:

function fetcher(locals) {
  return function _fetcher(callback) {
    // this function body will have access to locals
  }
}

并将您的代码重写为:

function task() {
    var locals = []    //<-- declared here
    async.series([
        fetcher(locals),    //<--  can now access "locals"
        parser(locals),     //<--  can now access "locals"
        saveToDb(locals)    //<--  can now access "locals"
    ],
            function (err) {
                if (err) return callback(err);
                callback(null);
    });
}

【讨论】:

  • 我不确定“async.series”是否接受“回调”以外的参数,我会检查一下。谢谢伙伴。
【解决方案3】:

如果我正确理解您的问题,这是一个 javascript 101 问题。

fetcher 可以是创建具体 fetcher 的工厂。

var fetcher = function(locals){
 locals=locals||[] // optional , assign a default , whatever ...
 return function(){
   //do some operation with locals.
   doSomething(locals);
 }
}

然后在你的脚本中

 async.series([
        fetcher(locals),    //<--  will return the callback to use
        parser(locals),     //<--  will return the callback to use
        saveToDb(locals)    //<--  will return the callback to use
    ],

我相信这是一种柯里化。

【讨论】:

  • "async.series" 除了“回调”(我认为)之外不接受任何参数,而且“locals”是我的主要“数据”——我不能每次都删除它。谢谢mpm。
猜你喜欢
  • 2016-07-31
  • 1970-01-01
  • 2015-06-22
  • 1970-01-01
  • 2014-12-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-01-01
相关资源
最近更新 更多