2014-11-21 79 views
0

我开始了一个新的节点项目,并想动态地添加路由。我之前做过这些,但从来没有深入过一层文件夹。 为此,我想出了一个递归函数来添加路线并遍历可能的子文件夹。该函数在我的app.js中调用。该项目的文件夹看起来是这样的:nodejs express递归路由失败(404)

app.js 
routes/ 
    index.js 
    users.js 
    api/ 
     foo.js 
     test/ 
      bar.js 

在app.js的定义和功能召唤:

var express = require('express'); 
var fs = require('fs'); 
var path = require('path'); 
var app = express(); 

// Works 
var routes = require('./routes/index'); 
app.use('/', routes); 


// 404 
getRoutes('routes'); 

function getRoutes(dir, cur) { 
    if(cur === undefined) { 
     cur = '/'; 
    } 
    routes = fs.readdirSync(path.join(__dirname, dir)); 
    routes.forEach(function (file) { 

     fs.stat(dir + "/" + file, function (err, stats) { 
      if (err) { 
       console.log(err); 
      } 
      else if (stats.isFile()) { 
       var routeFilePath = "./" + path.join(dir, file); 
       var route = path.join(cur, file.replace(/\.[^/.]+$/, ""))+'/'; 
       if(file == 'index.js') { 
        route = cur; 
       } 
       console.log(route, "defined in:", routeFilePath); 

       var routeFile = require(routeFilePath); 
       app.use(route, routeFile); 
      } 
      else if (stats.isDirectory()) { 
       getRoutes(path.join(dir, file), path.join(cur, file)); 
      } 
     }); 
    }); 
} 

请注意,是的app.use()作品直接调用。 有没有人看到错误?

console.log(route, "defined in:", routeFilePath);输出:

/ defined in: ./routes/index.js 
/users/ defined in: ./routes/users.js 
/api/foo/ defined in: ./routes/api/foo.js 
/api/test/bar/ defined in: ./routes/api/test/bar.js 

看起来正确的给我。

回答

0

问题是fs.stats()是异步的。路线必须同步定义,如:

function getRoutes(dir, cur) { 
    if(cur === undefined) { 
     cur = '/'; 
    } 
    routes = fs.readdirSync(path.join(__dirname, dir)); 
    routes.forEach(function (file) { 

     var stats = fs.statSync(dir + "/" + file); 
     if (stats.isFile()) { 
      var routeFilePath = "./" + path.join(dir, file); 
      var route = path.join(cur, file.replace(/\.[^/.]+$/, ""))+'/'; 
      if(file == 'index.js') { 
       route = cur; 
      } 
      console.log(route, "defined in:", routeFilePath); 

      var routeFile = require(routeFilePath.replace(/\.[^/.]+$/, "")); 
      console.log(routeFile); 
      app.use(route, routeFile); 
     } 
     else if (stats.isDirectory()) { 
      getRoutes(path.join(dir, file), path.join(cur, file)); 
     } 

    }); 
}