Node.js can';无法理解node/express4中的路由

Node.js can';无法理解node/express4中的路由,node.js,express,express-4,Node.js,Express,Express 4,请帮助解决路由问题: var express=require('express'); var path=require('path'); var favicon=要求('serve-favicon'); var记录器=需要('morgan'); var cookieParser=require('cookie-parser'); var bodyParser=require('body-parser'); var methodOverride=require('method-override'

请帮助解决路由问题:

var express=require('express');
var path=require('path');
var favicon=要求('serve-favicon');
var记录器=需要('morgan');
var cookieParser=require('cookie-parser');
var bodyParser=require('body-parser');
var methodOverride=require('method-override');
var router=express.router();
var-app=express();
//查看引擎设置
app.set('views',path.join('views');
app.engine('html',require('ejs').renderFile);
app.set('view engine','html');
//将您的favicon置于/公共位置后取消注释
//应用程序使用(favicon(path.join(u dirname,'public','favicon.ico'));
应用程序使用(记录器(“开发”);
use(bodyParser.json());
use(bodyParser.urlencoded({extended:false}));
使用(methodOverride());
使用(cookieParser());
app.use(express.static(path.join(uu dirname,'public'));
//内存中的数据存储
变量窗口小部件=[
{id:1,
名称:“我的特殊小部件”,
价格:100.00,
descr:“价格以外的小部件”},
];
//路线
应用程序使用(路由器);
router.get('/',函数(req,res,next){
res.render(“索引”);
});
router.get('/widgets',函数(req,res){
res.send(widgets);
});
router.post('/widgets/add',函数(req,res){
var indx=widgets.length+1;
widgets[widgets.length]={id:indx,
名称:req.body.widgetname,
价格:parseFloat(请求主体widgetprice),
descr:req.body.widgetdesc
};
log('added'+widgets[indx-1]);
res.send('Widget'+req.body.widgetname+'添加了id'+indx);
});
router.get('/widgets/:id',函数(req,res){
var indx=parseInt(请求参数id)-1;
如果(!widgets[indx]){
res.send('没有id为'+req.params.id'的小部件);
}否则{
res.send(widgets[indx]);
}
});
router.put('/widgets/:id/update',函数(req,res){
var indx=req.params.id-1;
widgets[indx]={id:indx,
名称:req.body.widgetname,
价格:parseFloat(请求主体widgetprice),
descr:req.body.widgetdesc};
log(widgets[indx]);
res.send('updated'+请求参数id);
});
删除('/widgets/:id/delete',函数(req,res){
var indx=req.params.id-1;
删除小部件[indx];
console.log('已删除'+请求参数id);
res.send('已删除'+请求参数id);
});
//捕获404并转发到错误处理程序
应用程序使用(功能(请求、恢复、下一步){
var err=新错误(“未找到”);
err.status=404;
下一个(错误);
});
//错误处理程序
//开发错误处理程序
//将打印stacktrace
if(app.get('env')='development'){
应用程序使用(功能(错误、请求、恢复、下一步){
资源状态(资源状态| | 500);
res.render('错误'{
message:err.message,
错误:错误
});
});
}
//生产错误处理程序
//没有堆栈跟踪泄漏给用户
应用程序使用(功能(错误、请求、恢复、下一步){
资源状态(资源状态| | 500);
res.render('错误'{
message:err.message,
错误:{}
});
});

module.exports=app此示例存在一些问题。我将从最重要的部分到最不重要的部分进行阐述

方法混淆 REST,或REpresentationalStateTtransfer,定义了具有不同目的的HTTP动词

  • 获取:获取资源
  • POST:创建一个资源
  • PUT:覆盖资源
  • 修补程序:部分修改资源
  • 删除:删除资源
  • 还有一些
需要注意的一点是,在express路由器中,即使URL相同,GET请求也不会被POST URL处理程序匹配。即使URL相同,操作也不同

因此,当您尝试发布到
/widgets/1/update
时看到404错误的原因是您没有定义发布处理程序,而是定义了放置处理程序

不正确的RESTURL 由于可以对同一URL执行多个操作,因此出现了一种标准。由于URL设计用于引用资源,而不是操作,所以请尽量避免使用URL中的操作词

比如说。不要为
/widgets/1/update
使用PUT处理程序,只需为
/widgets/1
执行PUT处理程序即可。您正在更新的事实已经很明显,因为您正在执行PUT请求

同样,为
/widgets/1
而不是
/widgets/1/DELETE
创建一个删除处理程序

请记住,这不会与
/widgets/1
的GET或DELETE处理程序冲突,因为动词是不同的

这篇文章有点不同。使用POST
/widgets
,而不是POST
/widgets/add

要描述这一点,如果你要说出你想做什么:

小部件中创建记录

发布到/widgets

“添加”或“创建”已经很明显了,因为这是一个POST请求

代码顺序 这是一个小小的抱怨。您正在
。在实际定义路由之前,请使用()。这是因为javascript是如何处理对象变量的,但它是向后看的

理解快车 代码中的
app
可以处理
.post()
.get()
等。没有理由在代码中构造和使用路由器

express.Router()
用于在部分URL上挂载一整组路径或在思想上保持一组URL的分离,例如:

var app = express()
var apiRoutes = require("./api-router")
var frontendRoutes = require("./frontend-router")

app.use("/api", apiRoutes)
app.use(frontendRoutes)