前言:
而今小伙伴们对“nodejs json对象”大致比较关心,各位老铁们都想要了解一些“nodejs json对象”的相关资讯。那么小编也在网摘上汇集了一些有关“nodejs json对象””的相关资讯,希望姐妹们能喜欢,同学们快快来学习一下吧!一、前端EventLoop
1、什么是eventLoop?
同步任务和异步任务在js中是如何执行的呢?js的代码运行会形成一个主线程和一个任务队列。主线程会从上到下一步步执行我们的js代码,形成一个执行栈。同步任务就会被放到这个执行栈中依次执行。而异步任务被放入到任务队列中执行,执行完就会在任务队列中打一个标记,形成一个对应的事件。当执行栈中的任务全部运行完毕,js会去提取并执行任务队列中的事件。这个过程是循环进行的,这就是我们今天想要了解的event loop
2、为什么js是单线程
想要了解event loop我们就要从js的工作原理说起。首先,大家都知道js是单线程的。所谓单线程就是进程中只有一个线程在运行。那么,js为什么是单线程而不是做成多线程的呢?个人理解,js是用来实现浏览器与用户之间的交互的。如果同时要处理用户点击,用户输入,用户关闭等操作,浏览器无法知道这个时间我到底应该做什么。所以js是从上至下按顺序运行下去的
3、什么是宏任务&&什么是微任务
宏任务: 需要多次事件循环才能执行完,事件队列中的每一个事件都是一个宏任务。浏览器为了能够使得js内部宏任务与DOM任务有序的执行,会在一个宏任务执行结束后,在下一个宏执行开始前,对页面进行重新渲染 (task->渲染->task->…)鼠标点击会触发一个事件回调,需要执行一个宏任务,然后解析HTML
微任务: 微任务是一次性执行完的。微任务通常来说是需要在当前task执行结束后立即执行的任务,例如对一些动作做出反馈或者异步执行任务又不需要分配一个新的task,这样便可以提高一些性能
4、案例
console.log("script start");•setTimeout(function(){ console.log("setTimeout");},0)•newPromise(resolve=>{ console.log("promise start"); resolve();}).then(function(){ console.log("promise1");}).then(()=>{ console.log("promise2");})•console.log("script end");console.log(1);•setTimeout(()=>{ console.log(2);})•newPromise((resolve)=>{ console.log(4) resolve()}).then(()=>{setTimeout(()=>{ console.log(5); })}).then(()=>{ console.log(6)})•console.log(7)setTimeout(() => { console.log(5)• new Promise(resolve => { console.log(6)• setTimeout(() => { console.log(7) }) resolve() }).then(() => { console.log(8) })}, 500)new Promise(resolve => { console.log(9) resolve()}).then(() => { console.log(10)• setTimeout(() => { console.log(11) }, 0)})•console.log(12)
二、后端EventLoop
1、NodeJS中的宏任务分类
Timers 类型的宏任务队列
setTimeout()setInterval
Check 类型的宏任务队列
setImmediate()
Close callback 类型的宏任务队列
socket.on(‘close’, () => {})
Poll 类型的宏任务队列
除了上面几种的其他所有回调
2、nodeJs 里面的微任务队列
process.nextTick()Promise.then() process.nextTick()的优先级高于所有的微任务,每一次清空微任务列表的时候,都是先执行process.nextTick()
3、setTimeout && setImmediate执行顺序
Node 并不能保证 timers 在预设时间到了就会立即执行,因为 Node 对 timers 的过期检查不一定靠谱,它会受机器上其它运行程序影响,或者那个时间点主线程不空闲
虽然 setTimeout 延时为 0,但是一般情况 Node 把 0 会设置为 1ms,所以,当 Node 准备 event loop 的时间大于 1ms 时,进入 timers 阶段时,setTimeout 已经到期,则会先执行 setTimeout;反之,若进入 timers 阶段用时小于 1ms,setTimeout 尚未到期,则会错过 timers 阶段,先进入 check 阶段,而先执行 setImmediate
三、postman的基本使用
1、打开postman之后,首先输入URL,方法选择GET
2、然后我们在Headers里面输入我们所需要的内容,如果需要Cookie也填写在这里面即可(不需要可以不填),填写的时候可以单个填写,也可以点击【Bulk Edit】进行填写方式切换,切换后可以一次填写所有内容
3、填写了Headers之后,如果这个get请求里面有传参,我们接下来可以填写参数,如果不需要也可以不填。填了参数之后,内容就会拼接在我们的url里面
4、最后,我们点击send,就可以看到返回值了
post同理
四、项目的基本搭建一、express生成器搭建项目结构
1、安装 express-generator
npm install express-generator -g
2、通过express -e生成项目结构
3、安装依赖
$ cd myapp
$ npm install
4、启动项目
npm start
二、MVC架构思想
MVC即Model-View-Controller(模型-视图-控制器)是一种软件设计模式,最早出现在Smalltalk语言中,后被Sun公司推荐为Java EE平台的设计模式。
MVC把应用程序分成了上面3个核心模块,这3个模块又可被称为业务层-视图层-控制层。顾名思义,它们三者在应用程序中的主要作用如下:
业务层:负责实现应用程序的业务逻辑,封装有各种对数据的处理方法。它不关心它会如何被视图层显示或被控制器调用,它只接受数据并处理,然后返回一个结果。
视图层:负责应用程序对用户的显示,它从用户那里获取输入数据并通过控制层传给业务层处理,然后再通过控制层获取业务层返回的结果并显示给用户。
控制层:负责控制应用程序的流程,它接收从视图层传过来的数据,然后选择业务层中的某个业务来处理,接收业务层返回的结果并选择视图层中的某个视图来显示结果。
可以用下图来表示MVC模式中三者之间的关系:
三、图片上传安装multer模块
npm install multer引用模块 它是依赖于express的一个模块
//引用express并配置var express = require("express");var app = express();app.listen(3000);var multer = require('multer');/*var upload = multer({ //如果用这种方法上传,要手动添加文明名后缀 //如果用下面配置的代码,则可以省略这一句 dest: 'uploads/'})*/配置 设置保存文件的地方,并根据上传的文件名对应文件添加后缀 可以通过filename属性定制文件保存的格式
属性值用途destination设置资源的保存路径。注意,如果没有这个配置项,默认会保存在/tmp/uploads下。此外,路径需要自己创建filename设置资源保存在本地的文件名
var storage = multer.diskStorage({ //设置上传后文件路径,uploads文件夹会自动创建。 destination: function(req, file, cb) { cb(null, './uploads') }, //给上传文件重命名,获取添加后缀名 filename: function(req, file, cb) { var fileFormat = (file.originalname).split("."); //给图片加上时间戳格式防止重名名 //比如把 abc.jpg图片切割为数组[abc,jpg],然后用数组长度-1来获取后缀名 cb(null, file.fieldname + '-' + Date.now() + "." + fileFormat[fileFormat.length - 1]); }});var upload = multer({ storage: storage});接受文件 upload.single('xxx'),xxx与表单中的name属性的值对应 这里虽然用到post请求,但实际上不需要bodyParser模块处理
app.post('/upload-single', upload.single('logo'), function(req, res, next) { console.log(req.file) console.log('文件类型:%s', req.file.mimetype); console.log('原始文件名:%s', req.file.originalname); console.log((req.file.originalname).split(".")) console.log('文件大小:%s', req.file.size); console.log('文件保存路径:%s', req.file.path); res.send({ ret_code: '0' });});多图上传 多图上传只要更改一下地方,前端往file输入框加多一个multiple="multiple"属性值,此时就可以在选图的时候多选了,当然也可以并列多个file输入框(不推荐多个上传图片输入框),这样体验会不好
<input type="file" name="logo" multiple="multiple" />
后端也需要相应的改变
app.post('/upload-single', upload.single('logo'), function(req, res, next) {//upload.single('logo')变为upload.array('logo', 2),数字代表可以接受多少张图片app.post('/upload-single', upload.array('logo', 2), function(req, res, next) {
如果不想有图片数量上传限制,我们可以用upload.any()方法
app.post('/upload-single', upload.any(), function(req, res, next) { res.append("Access-Control-Allow-Origin","*"); res.send({ wscats_code: '0' });});前端部分formData表单提交
<form action="; method="post" enctype="multipart/form-data"> <h2>单图上传</h2> <input type="file" name="logo"> <input type="submit" value="提交"></form>formData表单+ajax提交
<form id="uploadForm"> <p>指定文件名: <input type="text" name="filename" value="" /></p> <p>上传文件: <input type="file" name="logo" /></ p> <input type="button" value="上传" onclick="doUpload()" /></form>
FormData对象,是可以使用一系列的键值对来模拟一个完整的表单,然后使用XMLHttpRequest发送这个"表单"
注意点
processData设置为false。因为data值是FormData对象,不需要对数据做处理。<form>标签添加enctype="multipart/form-data"属性。cache设置为false,上传文件不需要缓存。contentType设置为false。因为是由<form>表单构造的FormData对象,且已经声明了属性enctype="multipart/form-data",所以这里设置为false
上传后,服务器端代码需要使用从查询参数名为logo获取文件输入流对象,因为<input>中声明的是name="logo"
function doUpload() { $.ajax({ url: ';, type: 'POST', cache: false, //不必须 data: new FormData($('#uploadForm')[0]), processData: false,//必须 contentType: false,//必须 success: function(data) { console.log(data) } })}
四、编写接口
api接口
RestfulApi 规范接口文档的生成(apidoc)接口请求方式区别
跨域解决
corsjsonpproxy
五、JWTJWT用户登录 服务器端产生一个token (加密字符串) 发送给前端前端将token 进行保存前端发起数据请求的时候携带token服务端 验证token 是否合法 如果合法继续操作 不合法终止操作token 的使用场景 无状态请求 保持用户的登录状态 第三方登录(token+auth2.0)
非对称加密 通过私钥产生token 通过公钥解密token
// 1.产生公钥和私钥// 产生私钥 openssl genrsa -out ./private_key.pem 1024 1024 代表私钥长度// 产生公钥 openssl rsa -in ./private_key.pem -pubout -out ./public_key.pem let private_key=fs.readFileSync(path.join(__dirname,'./private_key.pem')) let public_key=fs.readFileSync(path.join(__dirname,'./public_key.pem')) var token = jwt.sign(palyload, private_key,{ algorithm: 'RS256'}); console.log(token) let token='eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6IueUqOaIt2lkIiwiaWF0IjoxNTUxMTUyNzk1fQ.TI_xDBvObHGAH7EV40WWpQemm5nx077Gdjq-pzDx0NWN5YFd40S7XcLmgoDdYscLM7vMOP0c7z1l83JUixqk7IBjBCU-tMNo_G5_-LGkQjV3vDYq_3TkXTl42lgmFA-EBey7W6W1PgPfYlowyHAyp-07hXaMRevgVkXm2lPEFXo' var decoded = jwt.verify(token, public_key);
const jwt=require('jsonwebtoken')const scrict='sdjfksdjflajflasjflasjflksf'function creatToken(palyload){ // 产生token palyload.ctime=Date.now() return jwt.sign(palyload,scrict)}function checkToken(token){ return new Promise((resovle,reject)=>{ jwt.verify(token,scrict,(err,data)=>{ if(err){ reject('token 验证失败')} resovle(data) }) }) }module.exports={ creatToken,checkToken}
Cookie+Session
const cookieParse=require('cookie-parser')const session = require('express-session')app.use(session({ secret: 'hubwizApp', //为了安全性的考虑设置secret属性 cookie: {maxAge: 60 * 1000 * 60 * 24 }, //设置过期时间 resave: true, // 即使 session 没有被修改,也保存 session 值,默认为 true saveUninitialized: false, //无论有没有session cookie,每次请求都设置个session cookie ,默认给个标示为 connect.sid}));
登录成功
req.session.sign = true;req.session.name = us;
需要验证的接口判断是否存在
注销session
app.get('/out', function(req, res){ req.session.destroy(); res.redirect('/');})六、登录验证码
const svgCaptcha = require('svg-captcha');生成验证码 返回图片格式async generateVerifCode() { const codeConfig = { size: 4, // 验证码长度 ignoreChars: '0oO1ilI', // 验证码字符中排除 0oO1ilI noise: 2, // 干扰线条的数量 width: 160, height: 50, fontSize: 50, color: true, // 验证码的字符是否有颜色,默认没有,如果设定了背景,则默认有 background: '#eee', }; const captcha = svgCaptcha.create(codeConfig); this.ctx.session.verifCode = captcha.text.toLowerCase(); // 存session用于验证接口获取文字码 this.ctx.body = captcha.data; }
标签: #nodejs json对象 #js node对象 #nodejs 获取输入 #nodejs后端渲染 #nodejs能干什么