简体   繁体   中英

JavaScript variables hoisting in nodejs/async

In the next example I don't have access to variable "locals" inside the functions "fetcher", "parser" and "saveToDb".

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

In the next example "local"s is accessible . I just copyed the functions declarations from the requested modules, and pasted them straight inside "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);
    });
}

While this works - I do want to keep my code modular. How can I fix that ? Or - what I forgot here about the fundamentals of JavaScript ?

Thanks.

In the first example, the callbacks live in another scope so can't access locals .

You could create partial functions that get the locals variable passed as first argument, but that would require you to rewrite your callbacks.

// 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) { ... }

You can have the 3 mentionned functions defined like this :

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

and rewrite your code as:

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

IF i understand your problem correctly this is a javascript 101 question.

fetcher can be a factory that creates a concrete fetcher.

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

then in your script

 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
    ],

i believe it is a kind of currying.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM