简体   繁体   English

Node.js:中间件和回调函数的执行顺序?

[英]Node.js: order of execution of middleware and callback functions?

I am fairly new to node.js, I have a starting point as app.js , It calls a file called xmlParser.js which parses an input xml file using the xml2js node module. 我对node.js相当陌生,我的起点是app.js ,它调用了一个名为xmlParser.js的文件,该文件使用xml2js节点模块解析输入的xml文件。 This is what app.js looks like, 这就是app.js样子,

//include the modules
var express = require('express'),
    app = express(),
    ejs = require('ejs'),
    xmlParser = require('./utils/xmlParser.js');

//save the pain of writing .ejs after each render
app.set("view engine","ejs");

//these will hold the result of the function in the file xmlParser
var listJSON, logJSON = {};

app.get('/portfolio', function(req, res, next){
    //call parse function in file xmlParser.js
    xmlParser.parse(__dirname + "/xml/svn_log.xml", listJSON);
    xmlParser.parse(__dirname + "/xml/svn_list.xml", logJSON);
    console.log("middleware was excuted!");
    next();
}, function(req, res){
    console.log(listJSON);
});

Now this is how the file xmlParser.js looks like, 现在这就是xmlParser.js文件的样子,

//include the modules
var fs = require('fs'),
    xml2js = require('xml2js'),
    parser = new xml2js.Parser();

//this function parse xml file with name as filename to json and stores it in variable outputJSON
function parse(filename, outputJSON){
    fs.readFile(filename, function(err, data){
        if(err){
            console.log('cannot read file.');
        } else {
            parser.parseString(data, function(err, result){
                if(err) console.log('cannot parse file.');
                else {
                    outputJSON = result;
                }
            });
        }
    });
}

module.exports = {
    parse
}

Now when I run the application and go to route /portfolio I expect this to be printed: 现在,当我运行该应用程序并转到路由/portfolio我希望将其打印出来:

middleware was executed!
[object]

But this is what I'm getting on my node console, 但这就是我在节点控制台上得到的,

middleware was executed!
undefined

Now, What I want is the function in xmlParser.js executes and stores the parsed JSON object in the listJSON object which I pass to it. 现在,我想要的是xmlParser.js的函数执行并将已解析的JSON对象存储在我传递给它的listJSON对象中。 When I pass listJSON as the second argument to parse() function, is it pass by reference? 当我将listJSON作为第二个参数传递给parse()函数时,它是否通过引用传递? Why am I getting 'undefined printed when my function in the file xmlParser.js` stores an object in it? printed when my function in the file xmlParser.js中的printed when my function in the file存储对象printed when my function in the file为什么会得到“未定义的printed when my function in the file ”?

One problem is that your parse function calls fs.readFile and parser.parseString which are asynchronous. 一个问题是您的parse函数调用异步的fs.readFileparser.parseString Second problem is that you change the object in your function: JavaScript passes parameters by object sharing. 第二个问题是您在函数中更改了对象:JavaScript通过对象共享传递参数。 Meaning: primitive variables are passed by value: changing the parameters doesn't change the source variable. 含义:原始变量按值传递:更改参数不会更改源变量。 Non primitive variables like objects and arrays, cannot be changed either, but their properties can. 非原始变量(如对象和数组)也不能更改,但它们的属性也可以更改。

While indeed you call parse before you call next , asynchronosly reading the file, and then asynchronously parsing it, (without blocking your route code), makes next come sooner than the program finishes parsing the file. 确实在调用next之前调用了parse ,但是异步读取文件,然后异步解析(而不阻塞您的路由代码),使得next比程序完成解析文件的时间早。

What you can do is pipe your asynchrnous actions one by one, also make the parse return the result and you will set it after. 您可以做的是将异步动作一个接一个地传递,并使解析返回结果,然后进行设置。 First change your parse function to accept a callback and call it: 首先将您的parse函数更改为接受回调并调用它:

function parse(filename, callback){
    fs.readFile(filename, function(err, data){
        if(err){
            console.log('cannot read file.');
            return callback(err);
        } else {
            parser.parseString(data, function(err, result){
                if(err) {
                   console.log('cannot parse file.');
                   return callback(err);
                }
                else {

                    return callback(null, result);
                }
            });
        }
    });
}

Then, pipe your parse functions together with the next function: 然后,将解析函数与next函数一起传递:

app.get('/portfolio', function(req, res, next){
    xmlParser.parse(__dirname + "/xml/svn_log.xml", function(err,  list) {
      listJSON = list;
      xmlParser.parse(__dirname + "/xml/svn_list.xml", function(err, log) {
        logJSON = log;
        next();
      });
    });
    console.log("middleware was excuted!");
}, function(req, res){
    console.log(listJSON);
});

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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