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

时间:2016-10-08 23:36:04

标签: javascript json node.js express

我对node.js相当新,我有一个起点app.js,它调用一个名为xmlParser.js的文件,它使用xml2js节点模块解析输入的xml文件。这就是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);
});

现在这就是文件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
}

现在,当我运行应用程序并转到路由/portfolio时,我希望打印出来:

middleware was executed!
[object]

但这是我在节点控制台上获得的,

middleware was executed!
undefined

现在,我想要的是xmlParser.js中的函数执行并将解析后的JSON对象存储在我传递给它的listJSON对象中。当我将listJSON作为第二个参数传递给parse()函数时,是否通过引用传递?为什么我得到'undefined printed when my function in the file xmlParser.js`会在其中存储一个对象?

1 个答案:

答案 0 :(得分:1)

一个问题是您的parse函数调用fs.readFileparser.parseString是异步的。第二个问题是您更改了函数中的对象:JavaScript通过对象共享传递参数。含义:原始变量按值传递:更改参数不会更改源变量。非原始变量(如对象和数组)也不能更改,但它们的属性可以。

确实在调用parse之前调用next,异步读取文件,然后异步解析它(不阻止路由代码),使next早于程序完成解析文件。

你可以做的是逐个管理你的异步动作,也让解析返回结果,你将在之后设置它。首先更改您的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);
                }
            });
        }
    });
}

然后,将您的解析函数与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);
});