现在流行的: 前端渲染
问题: 当前后端同时进行项目开发是, 后端数据接口没有写好,但是前端却需要这个接口,这个时候怎么办?
分析: 需要一段数据
解决: 模拟假数据( mock数据 json-server / mock.js )
以上这种形式叫做 : 前后端架构分离
很久以前,没有前端岗位的, 所有的网页都需要后端完成, 那个时候的情况我们称之为: 前后端耦合
直接借助一个工具来搭建一个Node.js项目,这个工具叫做 express-generator ,这个工具帮助我们实现了express框架
创建express项目的流程
$ cnpm i express-generator -g
创建express 项目
$ express -e 项目名称
-e是安装 ejs 模板
分析目录
启动项目 package.json 中 npm 脚本
$ npm run start
研究项目代码
中间件是一个函数,函数中参数有三个:
中间件有三种类型
前端的请求方式有几种?
以上的请求方式统称为: restful api
restful是一个规则,这个规则规定了数据接口的使用原则
举例:
http:localhost:300/shopcar/add
http:localhost:300/shopcar/delete
http://localhost:300/shopcar
想: 如果能有一个接口来表示不同的请求功能,那会怎么样呢?
解决: restful api 这个规则
http://localhost:300/shopcar
get
post
put
delete
/*
1. async函数式由es6提供的
2. async函数的底层其实就是generator函数
3. async函数需要和关键字 await 搭配使用
4. async也是Promise,也可以调用.then
格式:
const asyncFn = async () => {
await 任务
}
var obj = {
async aa () {
await 任务
}
}
注意:
只有await后面的任务 顺利执行完成,那么下面的任务才会去执行,如果await后面的任务执行不顺利, 那么后面的任务会出问题
使用场景:
先进行数据请求,得到数据之后,在去操作这个数据 ,这个时候,我们的async就是首选
*/
// const asyncFn = async () => {
// const request = await '任务一'
// console.log(' 任务2 ')
// console.log( request )
// }
// asyncFn()
// console.log( '主线程任务' )
var obj = {
async aa () {
}
}
$.ajax({
success (res) {
console.log( res )
}
})
/*
Node.js提供的两个方法
1. nextTick
2. setimmediate
总结:
nextTick()的回调函数执行的优先级要高于setImmediate();
process.nextTick()属于idle观察者,setImmediate()属于check观察者.在每一轮循环检查中,idle观察者先于I/O观察者,I/O观察者先于check观察者.
- idle观察者,也就是事件轮询最先进行的任务
- I/O观察者, 也就是事件轮询中的任务(任务中的回调函数)
- check观察者 事件轮询中的任务的结束
在具体实现上,process.nextTick()的回调函数保存在一个数组中,
setImmediate()的结果则是保存在链表中.
在行为上,process.nextTick()在每轮循环中会将数组中的回调函数全部执行完.
而setImmediate()在每轮循环中执行链表中的一个回调函数.
使用格式:
process.nextTick( callback )
setImmediate( callback )
执行顺序
1. nextTick> setImmediate
2. nextTick 中 的nextTick 》 外层的setImmediate
3. 外层setImmediate > 内层的setImmediate
*/
process.nextTick( function () {
console.log('A')
process.nextTick( function(){
console.log('D')
})
setImmediate( function () {
console.log('E')
})
})
setImmediate( function () {
console.log( 'B' )
process.nextTick( function(){
console.log('F')
})
setImmediate( function () {
console.log('G')
})
})
process.nextTick( function () {
console.log( 'C')
})
console.log( '主线程任务' )
/*
$ node Nodejs.js
主线程任务
A
C
D
B
E
F
G
*/
/*
第三方的async函数
串行 : series
并行: parallel
串行格式:
async.series({ 任务名称: 任务值 },function( err, data ) {})
并行
async.parallel({ 任务名称: 任务值 },function( err, data ) {})
*/
var async = require( 'async' )
// async.series({
// one: function( callback ) {
// setTimeout ( function () {
// callback( null, '任务1' )
// },2000)
// },
// two: function ( callback ) {
// setTimeout ( function () {
// callback( null, '任务2')
// },1000)
// }
// },function ( err , data ) {
// console.log( data )
// })
//串行:里面的任务是等最慢的那个任务执行完成后再输出,这里是以最慢时间2s之后再把2个顺序输出
/*
$ node three-part-async.js
{ one: '任务1', two: '任务2' }
*/
async.parallel({
one: function ( callback ) {
setTimeout ( function () {
callback( null , '任务1')
},2000)
},
two: function ( callback ) {
setTimeout ( function () {
callback( null , '任务2')
},1000)
}
},function(error,data){
console.log( data )
console.log( '任务3' )
})
//并行:谁块谁先输出,最后是在任务一那个最慢的2s的执行完成,然后一并输出
/*
$ node three-part-async.js
{ two: '任务2', one: '任务1' }
任务3
*/
可以参考印象笔记(https://app.yinxiang.com/u/0/Home.action#n=cc293066-d1be-42e6-8c03-898757d8b631&s=s37&ses=4&sh=2&sds=2&)
{
"name": "2-npm-scripts",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"pretest": " echo \" pretest \" ",
"test": "echo \" test \" ",
"posttest": "echo \" posttest \"",
"server": "node server.js",
"dev": "node index.js",
"build": "npm run dev & npm run server ",
"yyb": " npm run dev && npm run server ",
"clean": "rimraf index.js"
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"request": "^2.88.0",
"rimraf": "^2.6.3"
}
}
console.log(process.env.npm_package_name)
console.log(process.env.npm_package_version)
var http = require( 'http' )
http.createServer( function ( req,res ) {
res.write( 'hello 520' )
res.end()
}).listen( 3000, 'localhost', function () {
console.log( '服务器运行在:http://localhost:3000' )
})
/* _name
中的‘_’来代表package.json中的name这个键
这样就可以获取这个键里面的值
*/
/* $ npm run dev */
/*
2-npm-scripts
1.0.0
*/
/* $ npm run start 可以简写为 $ npm start
它表示 "server": "node server.js",
其实运行 node server.js
*/
/*
如果配置文件里如下写
"pretest": " echo \" pretest \" ",
"test": "echo \" test \" ",
"posttest": "echo \" posttest \"",
执行 $ npm run test 输出如下:
> [email protected] pretest c:\wamp\www\sanjeiduan\1902\dom4(xiaowu)\2-npm-scripts
> echo " pretest "
" pretest "
> [email protected] test c:\wamp\www\sanjeiduan\1902\dom4(xiaowu)\2-npm-scripts
> echo " test "
" test "
> [email protected] posttest c:\wamp\www\sanjeiduan\1902\dom4(xiaowu)\2-npm-scripts
> echo " posttest "
" posttest "
*/
直接借助一个工具来搭建一个Node.js项目,这个工具叫做 express-generator ,这个工具帮助我们实现了express框架
$ cnpm i express-generator -g
创建express 项目
$ express -e 项目名称
-e是安装 ejs 模板
’项目名称‘为项目所在文件夹的名称
如:$ express -e 3-express
然后 按上面的提示要求
$ cd 3-express/
然后 $ cnpm i
或者
快速创建 npm init -y / cnpm init -y / yarn init -y
分析目录
启动项目 package.json 中 npm 脚本
$ npm run start
研究项目代码
APP.js里面的东西解释
// 引入项目所需要的第三方包
var createError = require('http-errors');
var express = require('express');
var path = require('path');
var cookieParser = require('cookie-parser');
var logger = require('morgan');
// 引入项目路由配置文件
var indexRouter = require('./routes/index');
var usersRouter = require('./routes/users');
// 创建app对象
var app = express();
// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'ejs');
// 应用级中间件
app.use(logger('dev'));
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));
// 路由级中间件
app.use('/', indexRouter);
app.use('/users', usersRouter);
// catch 404 and forward to error handler
app.use(function(req, res, next) {
next(createError(404));
});
// 错误处理中间件
// error handler
app.use(function(err, req, res, next) {
// set locals, only providing error in development
res.locals.message = err.message;
res.locals.error = req.app.get('env') === 'development' ? err : {};
// render the error page
res.status(err.status || 500);
res.render('error');
});
module.exports = app;
在bin里面的www文件中改成
server.listen(port,function(){
console.log( ‘服务器运行在: http://localhost:3000’ )
});
这样运行服务器
就可以输出大致的雏形