Node.js Koa2开发微信小程序服务端
<p>1、promise、async、await</p><div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">const</span> Koa = require(<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">koa</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">)
</span><span style="color: rgba(0, 0, 255, 1)">const</span> app = <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> Koa()
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 应用程序对象 有很多中间件
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 发送HTTP KOA 接收HTTP(使用中间件,中间件实际就是函数)
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> await: 1、求值关键字,不仅是promise,表达式也可以(100*100)
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 2、阻塞当前线程
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> async 只要函数前面加了async,返回的值就会被promise包裹
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 注册</span>
app.use(<span style="color: rgba(0, 0, 255, 1)">async</span> (ctx, next) =><span style="color: rgba(0, 0, 0, 1)"> {
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> ctx 上下文</span>
console.log(<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">1</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">)
</span><span style="color: rgba(0, 0, 255, 1)">const</span> a =<span style="color: rgba(0, 0, 255, 1)">await</span><span style="color: rgba(0, 0, 0, 1)"> next()
console.log(a)
console.log(</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">2</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">)
})
app.use(</span><span style="color: rgba(0, 0, 255, 1)">async</span> (ctx, next) =><span style="color: rgba(0, 0, 0, 1)"> {
console.log(</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">3</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">)
console.log(</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">4</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">)
</span><span style="color: rgba(0, 0, 255, 1)">return</span> <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">abc</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">
})
app.listen(</span><span style="color: rgba(128, 0, 128, 1)">3300</span>)</pre>
</div>
<pre>async 只要函数前面加了async,返回的值就会被promise包裹<br><br></pre>
<pre>await: 1、求值关键字,不仅是promise,表达式也可以(100*100)<br> 2、阻塞当前线程<br><br></pre>
<p> </p>
<p>2、</p>
<p>第一种情况</p>
<div class="cnblogs_code">
<pre>app.use((ctx, next) =><span style="color: rgba(0, 0, 0, 1)"> {
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> ctx 上下文</span>
console.log(<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">1</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">)
next()
console.log(</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">2</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">)
})
app.use(</span><span style="color: rgba(0, 0, 255, 1)">async</span> (ctx, next) =><span style="color: rgba(0, 0, 0, 1)"> {
console.log(</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">3</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">)
next()
console.log(</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">4</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">)
})
app.listen(</span><span style="color: rgba(128, 0, 128, 1)">3300</span>)</pre>
</div>
<p><img src="https://img2018.cnblogs.com/blog/1089823/201906/1089823-20190615111432668-1743050371.png"></p>
<p>这是因为node的洋葱模型,next()为中间分割点</p>
<p>第二种情况</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 注册</span>
app.use((ctx, next) =><span style="color: rgba(0, 0, 0, 1)"> {
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> ctx 上下文</span>
console.log(<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">1</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">)
next()
console.log(</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">2</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">)
})
app.use(</span><span style="color: rgba(0, 0, 255, 1)">async</span> (ctx, next) =><span style="color: rgba(0, 0, 0, 1)"> {
console.log(</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">3</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">)
</span><span style="color: rgba(0, 0, 255, 1)">const</span> axios = require(<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">axios</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">)
</span><span style="color: rgba(0, 0, 255, 1)">const</span> res =<span style="color: rgba(0, 0, 255, 1)">await</span> axios.<span style="color: rgba(0, 0, 255, 1)">get</span>(<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">http://7yue.pro</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">)
next()
console.log(</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">4</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">)
})
app.listen(</span><span style="color: rgba(128, 0, 128, 1)">3300</span>)</pre>
</div>
<p><img src="https://img2018.cnblogs.com/blog/1089823/201906/1089823-20190615112237479-722842634.png"></p>
<p>async await阻塞了当前线程,所以就跳转到其他线程</p>
<p>第三章情况:要想让中间件一直都执行洋葱模型,就需要在next前面使用await</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 注册</span>
app.use(<span style="color: rgba(0, 0, 255, 1)">async</span> (ctx, next) =><span style="color: rgba(0, 0, 0, 1)"> {
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> ctx 上下文</span>
console.log(<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">1</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">)
</span><span style="color: rgba(0, 0, 255, 1)">await</span><span style="color: rgba(0, 0, 0, 1)"> next()
console.log(</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">2</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">)
})
app.use(</span><span style="color: rgba(0, 0, 255, 1)">async</span> (ctx, next) =><span style="color: rgba(0, 0, 0, 1)"> {
console.log(</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">3</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">)
</span><span style="color: rgba(0, 0, 255, 1)">const</span> axios = require(<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">axios</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">)
</span><span style="color: rgba(0, 0, 255, 1)">const</span> res =<span style="color: rgba(0, 0, 255, 1)">await</span> axios.<span style="color: rgba(0, 0, 255, 1)">get</span>(<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">http://7yue.pro</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">)
</span><span style="color: rgba(0, 0, 255, 1)">await</span><span style="color: rgba(0, 0, 0, 1)"> next()
console.log(</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">4</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">)
})
app.listen(</span><span style="color: rgba(128, 0, 128, 1)">3300</span>)</pre>
</div>
<p> </p>
<p><img src="https://img2018.cnblogs.com/blog/1089823/201906/1089823-20190615112711579-1536147399.png"></p>
<p> 3、koa-router</p>
<p>https://www.npmjs.com/package/koa-router</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">const</span> Koa = require(<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">koa</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">)
</span><span style="color: rgba(0, 0, 255, 1)">const</span> Router = require(<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">koa-router</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">)
</span><span style="color: rgba(0, 0, 255, 1)">const</span> app = <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> Koa()
</span><span style="color: rgba(0, 0, 255, 1)">const</span> router = <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> Router()
router.</span><span style="color: rgba(0, 0, 255, 1)">get</span>(<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">/classic/latest</span><span style="color: rgba(128, 0, 0, 1)">'</span>, (ctx, next) =><span style="color: rgba(0, 0, 0, 1)"> {
ctx.body </span>= {key: <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">classic</span><span style="color: rgba(128, 0, 0, 1)">'</span>} <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 返回的信息</span>
<span style="color: rgba(0, 0, 0, 1)">})
app
.use(router.routes())
.use(router.allowedMethods)
app.listen(</span><span style="color: rgba(128, 0, 128, 1)">3300</span>)</pre>
</div>
<p> 4、exports和module.exports的区别</p>
<p>真正的是module.exports</p>
<p>module.exports是一个对象 module.exports={}</p>
<p>exports是module.exports的引用,类似于: var a= {},b=a;</p>
<p> 5、使用require-directory批量加载router</p>
<p>https://www.npmjs.com/package/require-directory</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">const</span> Koa = require(<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">koa</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">)
</span><span style="color: rgba(0, 0, 255, 1)">const</span> requireDirectory = require(<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">require-directory</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">)
</span><span style="color: rgba(0, 0, 255, 1)">const</span> Router = require(<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">koa-router</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">)
</span><span style="color: rgba(0, 0, 255, 1)">const</span> app = <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> Koa()
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 通过requireDirectory获取app/api/v1下的所有routers
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> visit: whenLoadModule 函数</span>
<span style="color: rgba(0, 0, 255, 1)">const</span> modules = requireDirectory(module, <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">./app/api/v1</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">, {
visit: whenLoadModule
})
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 用来判断引入的是router</span>
<span style="color: rgba(0, 0, 0, 1)">function whenLoadModule(obj) {
</span><span style="color: rgba(0, 0, 255, 1)">if</span><span style="color: rgba(0, 0, 0, 1)">(obj instanceof Router) {
app.use(obj.routes())
}
}
app.listen(</span><span style="color: rgba(128, 0, 128, 1)">3300</span>)</pre>
</div>
<p> 6、NodeJs中process.cwd()与__dirname的区别</p>
<p>process.cwd() 是当前执行node命令时候的文件夹地址 ——工作目录,保证了文件在不同的目录下执行时,路径始终不变<br>__dirname 是被执行的js 文件的地址 ——文件所在目录</p>
<p>Nodejs官方文档上的解释:</p>
<p>=> process.cwd(): The <code>process.cwd()</code> method returns the current working directory of theNode.js process.</p>
<p>意思很明了啦,就是说process.cwd()返回的是当前Node.js进程执行时的工作目录</p>
<p>那么来看看__dirname的官方解释:</p>
<p>=> __dirname: 当前模块的目录名。 等同于 <code>__filename</code> 的 <code>path.dirname()</code>。<code>__dirname</code> 实际上不是一个全局变量,而是每个模块内部的。</p>
<p>7、Node koa2中获取参数</p>
<p>http://localhost:3300/v1/:1/classic/latest?param=8yue</p>
<div class="cnblogs_code">
<pre>router.post(<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">/v1/:id/classic/latest</span><span style="color: rgba(128, 0, 0, 1)">'</span>, (ctx, next) =><span style="color: rgba(0, 0, 0, 1)"> {
</span><span style="color: rgba(0, 0, 255, 1)">const</span> path = ctx.<span style="color: rgba(0, 0, 255, 1)">params</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 获取的是:id里的值 1</span>
<span style="color: rgba(0, 0, 255, 1)">const</span> query = ctx.request.query <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 获取的是?param的值 8yue</span>
<span style="color: rgba(0, 0, 255, 1)">const</span> headers = ctx.request.header <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> header传递的值</span>
<span style="color: rgba(0, 0, 255, 1)">const</span> body = ctx.request.body <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> body里的值,json格式</span>
<span style="color: rgba(0, 0, 0, 1)">
ctx.body </span>=<span style="color: rgba(0, 0, 0, 1)"> {
key: </span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">classic</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">
}
})</span></pre>
</div>
<p> 8、如果是异步操作,而且用的是promise,一定要加上async、await</p>
<p>而且要用try ctach处理异常</p>
<p>9、定义错误基类</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> HttpException extends Error {
constructor (msg </span>= <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">服务器异常</span><span style="color: rgba(128, 0, 0, 1)">'</span>, errorCode = <span style="color: rgba(128, 0, 128, 1)">10000</span>, code = <span style="color: rgba(128, 0, 128, 1)">400</span><span style="color: rgba(0, 0, 0, 1)">) {
super()
</span><span style="color: rgba(0, 0, 255, 1)">this</span>.msg =<span style="color: rgba(0, 0, 0, 1)"> msg
</span><span style="color: rgba(0, 0, 255, 1)">this</span>.errorCode =<span style="color: rgba(0, 0, 0, 1)"> errorCode
</span><span style="color: rgba(0, 0, 255, 1)">this</span>.code =<span style="color: rgba(0, 0, 0, 1)"> code
}
}</span></pre>
</div>
<p>使用</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">const</span> { HttpException } = require(<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">../../../core/http-exception</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">)
</span><span style="color: rgba(0, 0, 255, 1)">const</span> error = <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> HttpException()
</span><span style="color: rgba(0, 0, 255, 1)">throw</span> error</pre>
</div>
<p>在中间件里throw出error,这样才能被try...catch捕获</p>
<p>10、特定异常类</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> ParameterException extends HttpException {
constructor (msg, errorCode) {
super()
</span><span style="color: rgba(0, 0, 255, 1)">this</span>.errorCode = errorCode || <span style="color: rgba(128, 0, 128, 1)">10000</span>
<span style="color: rgba(0, 0, 255, 1)">this</span>.msg = msg || <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">参数错误</span><span style="color: rgba(128, 0, 0, 1)">'</span>
<span style="color: rgba(0, 0, 255, 1)">this</span>.code = <span style="color: rgba(128, 0, 128, 1)">400</span><span style="color: rgba(0, 0, 0, 1)">
}
}
module.exports </span>=<span style="color: rgba(0, 0, 0, 1)"> {
HttpException,
ParameterException
}</span></pre>
</div>
<p>使用</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">const</span> { ParameterException } = require(<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">../../../core/http-exception</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">)
</span><span style="color: rgba(0, 0, 255, 1)">const</span> error = <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> ParameterException()
</span><span style="color: rgba(0, 0, 255, 1)">throw</span> error</pre>
</div>
<p>优化</p>
<p>每次使用错误的时候,都需要引入,然后new,可以把这个错误放到global里面</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">static</span><span style="color: rgba(0, 0, 0, 1)"> loadHttpException() {
</span><span style="color: rgba(0, 0, 255, 1)">const</span> errors = require(<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">./http-exception</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">)
</span><span style="color: rgba(0, 0, 255, 1)">global</span>.errs =<span style="color: rgba(0, 0, 0, 1)"> errors
}</span></pre>
</div>
<p>使用</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">const</span> error = <span style="color: rgba(0, 0, 255, 1)">new</span> <span style="color: rgba(0, 0, 255, 1)">global</span><span style="color: rgba(0, 0, 0, 1)">.errs.ParameterException()
</span><span style="color: rgba(0, 0, 255, 1)">throw</span> error</pre>
</div>
<p>这俩种方法都可以使用,看自己喜欢</p>
<p>11、async、await进行全局异常处理可以使用try...catch</p>
<p>在项目中,我们如果给每一个使用async、await的函数使用try...catch,这样太麻烦,我们可以定义一个全局异常处理中间件</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">const</span> { HttpException } = require(<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">../core/http-exception</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">)
</span><span style="color: rgba(0, 0, 255, 1)">const</span> catchError = <span style="color: rgba(0, 0, 255, 1)">async</span> (ctx, next) =><span style="color: rgba(0, 0, 0, 1)"> {
</span><span style="color: rgba(0, 0, 255, 1)">try</span><span style="color: rgba(0, 0, 0, 1)"> {
</span><span style="color: rgba(0, 0, 255, 1)">await</span> next() <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 有了next,函数调用后就会触发</span>
} <span style="color: rgba(0, 0, 255, 1)">catch</span><span style="color: rgba(0, 0, 0, 1)"> (error) {
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 判断error是否是HttpException</span>
<span style="color: rgba(0, 0, 255, 1)">if</span><span style="color: rgba(0, 0, 0, 1)"> (error instanceof HttpException) {
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 返回的错误信息</span>
ctx.body =<span style="color: rgba(0, 0, 0, 1)"> {
mag: error.msg,
error_code: error.errorCode,
request: `${ctx.method} ${ctx.path}`
}
ctx.status </span>=<span style="color: rgba(0, 0, 0, 1)"> error.code
}
}
}
module.exports </span>= catchError</pre>
</div>
<p>app.js</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">const</span> catchError = require(<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">./middlewares/exception</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">)
app.use(catchError)</span></pre>
</div>
<p>这样就注册了一个全局异常处理中间件,只要Node里有中间件运行时抛出异常,就会被这个中间件捕获</p>
<p> </p>
<p>12、LinValidator校验器 http://doc.cms.7yue.pro/lin/server/koa/validator.html#类校验</p>
<p>是用方式:</p>
<p> (1)、npm install validator --save-dev</p>
<p> (2)、创建lin-validator.js和util.js</p>
<p> lin-validator.js</p>
<p> </p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 128, 0, 1)">/*</span><span style="color: rgba(0, 128, 0, 1)">*
* Lin-Validator v1
* 作者:7七月
* 微信公众号:林间有风
</span><span style="color: rgba(0, 128, 0, 1)">*/</span>
<span style="color: rgba(0, 0, 255, 1)">const</span> validator = require(<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">validator</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">)
</span><span style="color: rgba(0, 0, 255, 1)">const</span><span style="color: rgba(0, 0, 0, 1)"> {
ParameterException
} </span>= require(<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">./http-exception</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">)
</span><span style="color: rgba(0, 0, 255, 1)">const</span><span style="color: rgba(0, 0, 0, 1)"> {
</span><span style="color: rgba(0, 0, 255, 1)">get</span><span style="color: rgba(0, 0, 0, 1)">,
last,
</span><span style="color: rgba(0, 0, 255, 1)">set</span><span style="color: rgba(0, 0, 0, 1)">,
cloneDeep
} </span>= require(<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">lodash</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">)
</span><span style="color: rgba(0, 0, 255, 1)">const</span><span style="color: rgba(0, 0, 0, 1)"> {
findMembers
} </span>= require(<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">./util</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">)
</span><span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> LinValidator {
constructor() {
</span><span style="color: rgba(0, 0, 255, 1)">this</span>.data =<span style="color: rgba(0, 0, 0, 1)"> {}
</span><span style="color: rgba(0, 0, 255, 1)">this</span>.parsed =<span style="color: rgba(0, 0, 0, 1)"> {}
}
_assembleAllParams(ctx) {
</span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> {
body: ctx.request.body,
query: ctx.request.query,
path: ctx.</span><span style="color: rgba(0, 0, 255, 1)">params</span><span style="color: rgba(0, 0, 0, 1)">,
header: ctx.request.header
}
}
</span><span style="color: rgba(0, 0, 255, 1)">get</span>(path, parsed = <span style="color: rgba(0, 0, 255, 1)">true</span><span style="color: rgba(0, 0, 0, 1)">) {
</span><span style="color: rgba(0, 0, 255, 1)">if</span><span style="color: rgba(0, 0, 0, 1)"> (parsed) {
</span><span style="color: rgba(0, 0, 255, 1)">const</span> value = <span style="color: rgba(0, 0, 255, 1)">get</span>(<span style="color: rgba(0, 0, 255, 1)">this</span>.parsed, path, <span style="color: rgba(0, 0, 255, 1)">null</span><span style="color: rgba(0, 0, 0, 1)">)
</span><span style="color: rgba(0, 0, 255, 1)">if</span> (value == <span style="color: rgba(0, 0, 255, 1)">null</span><span style="color: rgba(0, 0, 0, 1)">) {
</span><span style="color: rgba(0, 0, 255, 1)">const</span> keys = path.split(<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">.</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">)
</span><span style="color: rgba(0, 0, 255, 1)">const</span> key =<span style="color: rgba(0, 0, 0, 1)"> last(keys)
</span><span style="color: rgba(0, 0, 255, 1)">return</span> <span style="color: rgba(0, 0, 255, 1)">get</span>(<span style="color: rgba(0, 0, 255, 1)">this</span>.parsed.<span style="color: rgba(0, 0, 255, 1)">default</span><span style="color: rgba(0, 0, 0, 1)">, key)
}
</span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> value
} </span><span style="color: rgba(0, 0, 255, 1)">else</span><span style="color: rgba(0, 0, 0, 1)"> {
</span><span style="color: rgba(0, 0, 255, 1)">return</span> <span style="color: rgba(0, 0, 255, 1)">get</span>(<span style="color: rgba(0, 0, 255, 1)">this</span><span style="color: rgba(0, 0, 0, 1)">.data, path)
}
}
_findMembersFilter(key) {
</span><span style="color: rgba(0, 0, 255, 1)">if</span> (/validate()\w+/<span style="color: rgba(0, 0, 0, 1)">g.test(key)) {
</span><span style="color: rgba(0, 0, 255, 1)">return</span> <span style="color: rgba(0, 0, 255, 1)">true</span><span style="color: rgba(0, 0, 0, 1)">
}
</span><span style="color: rgba(0, 0, 255, 1)">if</span> (<span style="color: rgba(0, 0, 255, 1)">this</span><span style="color: rgba(0, 0, 0, 1)"> instanceof Array) {
</span><span style="color: rgba(0, 0, 255, 1)">this</span>.forEach(value =><span style="color: rgba(0, 0, 0, 1)"> {
</span><span style="color: rgba(0, 0, 255, 1)">const</span> isRuleType =<span style="color: rgba(0, 0, 0, 1)"> value instanceof Rule
</span><span style="color: rgba(0, 0, 255, 1)">if</span> (!<span style="color: rgba(0, 0, 0, 1)">isRuleType) {
</span><span style="color: rgba(0, 0, 255, 1)">throw</span> <span style="color: rgba(0, 0, 255, 1)">new</span> Error(<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">验证数组必须全部为Rule类型</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">)
}
})
</span><span style="color: rgba(0, 0, 255, 1)">return</span> <span style="color: rgba(0, 0, 255, 1)">true</span><span style="color: rgba(0, 0, 0, 1)">
}
</span><span style="color: rgba(0, 0, 255, 1)">return</span> <span style="color: rgba(0, 0, 255, 1)">false</span><span style="color: rgba(0, 0, 0, 1)">
}
validate(ctx, alias </span>=<span style="color: rgba(0, 0, 0, 1)"> {}) {
</span><span style="color: rgba(0, 0, 255, 1)">this</span>.alias =<span style="color: rgba(0, 0, 0, 1)"> alias
let </span><span style="color: rgba(0, 0, 255, 1)">params</span> = <span style="color: rgba(0, 0, 255, 1)">this</span><span style="color: rgba(0, 0, 0, 1)">._assembleAllParams(ctx)
</span><span style="color: rgba(0, 0, 255, 1)">this</span>.data = cloneDeep(<span style="color: rgba(0, 0, 255, 1)">params</span><span style="color: rgba(0, 0, 0, 1)">)
</span><span style="color: rgba(0, 0, 255, 1)">this</span>.parsed = cloneDeep(<span style="color: rgba(0, 0, 255, 1)">params</span><span style="color: rgba(0, 0, 0, 1)">)
</span><span style="color: rgba(0, 0, 255, 1)">const</span> memberKeys = findMembers(<span style="color: rgba(0, 0, 255, 1)">this</span><span style="color: rgba(0, 0, 0, 1)">, {
filter: </span><span style="color: rgba(0, 0, 255, 1)">this</span>._findMembersFilter.bind(<span style="color: rgba(0, 0, 255, 1)">this</span><span style="color: rgba(0, 0, 0, 1)">)
})
</span><span style="color: rgba(0, 0, 255, 1)">const</span> errorMsgs =<span style="color: rgba(0, 0, 0, 1)"> []
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> const map = new Map(memberKeys)</span>
<span style="color: rgba(0, 0, 255, 1)">for</span><span style="color: rgba(0, 0, 0, 1)"> (let key of memberKeys) {
</span><span style="color: rgba(0, 0, 255, 1)">const</span> result = <span style="color: rgba(0, 0, 255, 1)">this</span><span style="color: rgba(0, 0, 0, 1)">._check(key, alias)
</span><span style="color: rgba(0, 0, 255, 1)">if</span> (!<span style="color: rgba(0, 0, 0, 1)">result.success) {
errorMsgs.push(result.msg)
}
}
</span><span style="color: rgba(0, 0, 255, 1)">if</span> (errorMsgs.length != <span style="color: rgba(128, 0, 128, 1)">0</span><span style="color: rgba(0, 0, 0, 1)">) {
</span><span style="color: rgba(0, 0, 255, 1)">throw</span> <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> ParameterException(errorMsgs)
}
ctx.v </span>= <span style="color: rgba(0, 0, 255, 1)">this</span>
<span style="color: rgba(0, 0, 255, 1)">return</span> <span style="color: rgba(0, 0, 255, 1)">this</span><span style="color: rgba(0, 0, 0, 1)">
}
_check(key, alias </span>=<span style="color: rgba(0, 0, 0, 1)"> {}) {
</span><span style="color: rgba(0, 0, 255, 1)">const</span> isCustomFunc = <span style="color: rgba(0, 0, 255, 1)">typeof</span> (<span style="color: rgba(0, 0, 255, 1)">this</span>) == <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">function</span><span style="color: rgba(128, 0, 0, 1)">'</span> ? <span style="color: rgba(0, 0, 255, 1)">true</span> : <span style="color: rgba(0, 0, 255, 1)">false</span><span style="color: rgba(0, 0, 0, 1)">
let result;
</span><span style="color: rgba(0, 0, 255, 1)">if</span><span style="color: rgba(0, 0, 0, 1)"> (isCustomFunc) {
</span><span style="color: rgba(0, 0, 255, 1)">try</span><span style="color: rgba(0, 0, 0, 1)"> {
</span><span style="color: rgba(0, 0, 255, 1)">this</span>(<span style="color: rgba(0, 0, 255, 1)">this</span><span style="color: rgba(0, 0, 0, 1)">.data)
result </span>= <span style="color: rgba(0, 0, 255, 1)">new</span> RuleResult(<span style="color: rgba(0, 0, 255, 1)">true</span><span style="color: rgba(0, 0, 0, 1)">)
} </span><span style="color: rgba(0, 0, 255, 1)">catch</span><span style="color: rgba(0, 0, 0, 1)"> (error) {
result </span>= <span style="color: rgba(0, 0, 255, 1)">new</span> RuleResult(<span style="color: rgba(0, 0, 255, 1)">false</span>, error.msg || error.message || <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">参数错误</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">)
}
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 函数验证</span>
} <span style="color: rgba(0, 0, 255, 1)">else</span><span style="color: rgba(0, 0, 0, 1)"> {
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 属性验证, 数组,内有一组Rule</span>
<span style="color: rgba(0, 0, 255, 1)">const</span> rules = <span style="color: rgba(0, 0, 255, 1)">this</span><span style="color: rgba(0, 0, 0, 1)">
</span><span style="color: rgba(0, 0, 255, 1)">const</span> ruleField = <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> RuleField(rules)
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 别名替换</span>
key = alias ?<span style="color: rgba(0, 0, 0, 1)"> alias : key
</span><span style="color: rgba(0, 0, 255, 1)">const</span> param = <span style="color: rgba(0, 0, 255, 1)">this</span><span style="color: rgba(0, 0, 0, 1)">._findParam(key)
result </span>=<span style="color: rgba(0, 0, 0, 1)"> ruleField.validate(param.value)
</span><span style="color: rgba(0, 0, 255, 1)">if</span><span style="color: rgba(0, 0, 0, 1)"> (result.pass) {
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 如果参数路径不存在,往往是因为用户传了空值,而又设置了默认值</span>
<span style="color: rgba(0, 0, 255, 1)">if</span> (param.path.length == <span style="color: rgba(128, 0, 128, 1)">0</span><span style="color: rgba(0, 0, 0, 1)">) {
</span><span style="color: rgba(0, 0, 255, 1)">set</span>(<span style="color: rgba(0, 0, 255, 1)">this</span>.parsed, [<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">default</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">, key], result.legalValue)
} </span><span style="color: rgba(0, 0, 255, 1)">else</span><span style="color: rgba(0, 0, 0, 1)"> {
</span><span style="color: rgba(0, 0, 255, 1)">set</span>(<span style="color: rgba(0, 0, 255, 1)">this</span><span style="color: rgba(0, 0, 0, 1)">.parsed, param.path, result.legalValue)
}
}
}
</span><span style="color: rgba(0, 0, 255, 1)">if</span> (!<span style="color: rgba(0, 0, 0, 1)">result.pass) {
</span><span style="color: rgba(0, 0, 255, 1)">const</span> msg = `${isCustomFunc ? <span style="color: rgba(128, 0, 0, 1)">''</span><span style="color: rgba(0, 0, 0, 1)"> : key}${result.msg}`
</span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> {
msg: msg,
success: </span><span style="color: rgba(0, 0, 255, 1)">false</span><span style="color: rgba(0, 0, 0, 1)">
}
}
</span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> {
msg: </span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">ok</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">,
success: </span><span style="color: rgba(0, 0, 255, 1)">true</span><span style="color: rgba(0, 0, 0, 1)">
}
}
_findParam(key) {
let value
value </span>= <span style="color: rgba(0, 0, 255, 1)">get</span>(<span style="color: rgba(0, 0, 255, 1)">this</span>.data, [<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">query</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">, key])
</span><span style="color: rgba(0, 0, 255, 1)">if</span><span style="color: rgba(0, 0, 0, 1)"> (value) {
</span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> {
value,
path: [</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">query</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">, key]
}
}
value </span>= <span style="color: rgba(0, 0, 255, 1)">get</span>(<span style="color: rgba(0, 0, 255, 1)">this</span>.data, [<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">body</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">, key])
</span><span style="color: rgba(0, 0, 255, 1)">if</span><span style="color: rgba(0, 0, 0, 1)"> (value) {
</span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> {
value,
path: [</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">body</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">, key]
}
}
value </span>= <span style="color: rgba(0, 0, 255, 1)">get</span>(<span style="color: rgba(0, 0, 255, 1)">this</span>.data, [<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">path</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">, key])
</span><span style="color: rgba(0, 0, 255, 1)">if</span><span style="color: rgba(0, 0, 0, 1)"> (value) {
</span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> {
value,
path: [</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">path</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">, key]
}
}
value </span>= <span style="color: rgba(0, 0, 255, 1)">get</span>(<span style="color: rgba(0, 0, 255, 1)">this</span>.data, [<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">header</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">, key])
</span><span style="color: rgba(0, 0, 255, 1)">if</span><span style="color: rgba(0, 0, 0, 1)"> (value) {
</span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> {
value,
path: [</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">header</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">, key]
}
}
</span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> {
value: </span><span style="color: rgba(0, 0, 255, 1)">null</span><span style="color: rgba(0, 0, 0, 1)">,
path: []
}
}
}
</span><span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> RuleResult {
constructor(pass, msg </span>= <span style="color: rgba(128, 0, 0, 1)">''</span><span style="color: rgba(0, 0, 0, 1)">) {
Object.assign(</span><span style="color: rgba(0, 0, 255, 1)">this</span><span style="color: rgba(0, 0, 0, 1)">, {
pass,
msg
})
}
}
</span><span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> RuleFieldResult extends RuleResult {
constructor(pass, msg </span>= <span style="color: rgba(128, 0, 0, 1)">''</span>, legalValue = <span style="color: rgba(0, 0, 255, 1)">null</span><span style="color: rgba(0, 0, 0, 1)">) {
super(pass, msg)
</span><span style="color: rgba(0, 0, 255, 1)">this</span>.legalValue =<span style="color: rgba(0, 0, 0, 1)"> legalValue
}
}
</span><span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> Rule {
constructor(name, msg, ...</span><span style="color: rgba(0, 0, 255, 1)">params</span><span style="color: rgba(0, 0, 0, 1)">) {
Object.assign(</span><span style="color: rgba(0, 0, 255, 1)">this</span><span style="color: rgba(0, 0, 0, 1)">, {
name,
msg,
</span><span style="color: rgba(0, 0, 255, 1)">params</span><span style="color: rgba(0, 0, 0, 1)">
})
}
validate(field) {
</span><span style="color: rgba(0, 0, 255, 1)">if</span> (<span style="color: rgba(0, 0, 255, 1)">this</span>.name == <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">optional</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">)
</span><span style="color: rgba(0, 0, 255, 1)">return</span> <span style="color: rgba(0, 0, 255, 1)">new</span> RuleResult(<span style="color: rgba(0, 0, 255, 1)">true</span><span style="color: rgba(0, 0, 0, 1)">)
</span><span style="color: rgba(0, 0, 255, 1)">if</span> (!validator[<span style="color: rgba(0, 0, 255, 1)">this</span>.name](field + <span style="color: rgba(128, 0, 0, 1)">''</span>, ...<span style="color: rgba(0, 0, 255, 1)">this</span>.<span style="color: rgba(0, 0, 255, 1)">params</span><span style="color: rgba(0, 0, 0, 1)">)) {
</span><span style="color: rgba(0, 0, 255, 1)">return</span> <span style="color: rgba(0, 0, 255, 1)">new</span> RuleResult(<span style="color: rgba(0, 0, 255, 1)">false</span>, <span style="color: rgba(0, 0, 255, 1)">this</span>.msg || <span style="color: rgba(0, 0, 255, 1)">this</span>.message || <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">参数错误</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">)
}
</span><span style="color: rgba(0, 0, 255, 1)">return</span> <span style="color: rgba(0, 0, 255, 1)">new</span> RuleResult(<span style="color: rgba(0, 0, 255, 1)">true</span>, <span style="color: rgba(128, 0, 0, 1)">''</span><span style="color: rgba(0, 0, 0, 1)">)
}
}
</span><span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> RuleField {
constructor(rules) {
</span><span style="color: rgba(0, 0, 255, 1)">this</span>.rules =<span style="color: rgba(0, 0, 0, 1)"> rules
}
validate(field) {
</span><span style="color: rgba(0, 0, 255, 1)">if</span> (field == <span style="color: rgba(0, 0, 255, 1)">null</span><span style="color: rgba(0, 0, 0, 1)">) {
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 如果字段为空</span>
<span style="color: rgba(0, 0, 255, 1)">const</span> allowEmpty = <span style="color: rgba(0, 0, 255, 1)">this</span><span style="color: rgba(0, 0, 0, 1)">._allowEmpty()
</span><span style="color: rgba(0, 0, 255, 1)">const</span> defaultValue = <span style="color: rgba(0, 0, 255, 1)">this</span><span style="color: rgba(0, 0, 0, 1)">._hasDefault()
</span><span style="color: rgba(0, 0, 255, 1)">if</span><span style="color: rgba(0, 0, 0, 1)"> (allowEmpty) {
</span><span style="color: rgba(0, 0, 255, 1)">return</span> <span style="color: rgba(0, 0, 255, 1)">new</span> RuleFieldResult(<span style="color: rgba(0, 0, 255, 1)">true</span>, <span style="color: rgba(128, 0, 0, 1)">''</span><span style="color: rgba(0, 0, 0, 1)">, defaultValue)
} </span><span style="color: rgba(0, 0, 255, 1)">else</span><span style="color: rgba(0, 0, 0, 1)"> {
</span><span style="color: rgba(0, 0, 255, 1)">return</span> <span style="color: rgba(0, 0, 255, 1)">new</span> RuleFieldResult(<span style="color: rgba(0, 0, 255, 1)">false</span>, <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">字段是必填参数</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">)
}
}
</span><span style="color: rgba(0, 0, 255, 1)">const</span> filedResult = <span style="color: rgba(0, 0, 255, 1)">new</span> RuleFieldResult(<span style="color: rgba(0, 0, 255, 1)">false</span><span style="color: rgba(0, 0, 0, 1)">)
</span><span style="color: rgba(0, 0, 255, 1)">for</span> (let rule of <span style="color: rgba(0, 0, 255, 1)">this</span><span style="color: rgba(0, 0, 0, 1)">.rules) {
let result </span>=<span style="color: rgba(0, 0, 0, 1)"> rule.validate(field)
</span><span style="color: rgba(0, 0, 255, 1)">if</span> (!<span style="color: rgba(0, 0, 0, 1)">result.pass) {
filedResult.msg </span>=<span style="color: rgba(0, 0, 0, 1)"> result.msg
filedResult.legalValue </span>= <span style="color: rgba(0, 0, 255, 1)">null</span>
<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 一旦一条校验规则不通过,则立即终止这个字段的验证</span>
<span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> filedResult
}
}
</span><span style="color: rgba(0, 0, 255, 1)">return</span> <span style="color: rgba(0, 0, 255, 1)">new</span> RuleFieldResult(<span style="color: rgba(0, 0, 255, 1)">true</span>, <span style="color: rgba(128, 0, 0, 1)">''</span>, <span style="color: rgba(0, 0, 255, 1)">this</span><span style="color: rgba(0, 0, 0, 1)">._convert(field))
}
_convert(value) {
</span><span style="color: rgba(0, 0, 255, 1)">for</span> (let rule of <span style="color: rgba(0, 0, 255, 1)">this</span><span style="color: rgba(0, 0, 0, 1)">.rules) {
</span><span style="color: rgba(0, 0, 255, 1)">if</span> (rule.name == <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">isInt</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">) {
</span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> parseInt(value)
}
</span><span style="color: rgba(0, 0, 255, 1)">if</span> (rule.name == <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">isFloat</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">) {
</span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> parseFloat(value)
}
</span><span style="color: rgba(0, 0, 255, 1)">if</span> (rule.name == <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">isBoolean</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">) {
</span><span style="color: rgba(0, 0, 255, 1)">return</span> value ? <span style="color: rgba(0, 0, 255, 1)">true</span> : <span style="color: rgba(0, 0, 255, 1)">false</span><span style="color: rgba(0, 0, 0, 1)">
}
}
</span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> value
}
_allowEmpty() {
</span><span style="color: rgba(0, 0, 255, 1)">for</span> (let rule of <span style="color: rgba(0, 0, 255, 1)">this</span><span style="color: rgba(0, 0, 0, 1)">.rules) {
</span><span style="color: rgba(0, 0, 255, 1)">if</span> (rule.name == <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">optional</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">) {
</span><span style="color: rgba(0, 0, 255, 1)">return</span> <span style="color: rgba(0, 0, 255, 1)">true</span><span style="color: rgba(0, 0, 0, 1)">
}
}
</span><span style="color: rgba(0, 0, 255, 1)">return</span> <span style="color: rgba(0, 0, 255, 1)">false</span><span style="color: rgba(0, 0, 0, 1)">
}
_hasDefault() {
</span><span style="color: rgba(0, 0, 255, 1)">for</span> (let rule of <span style="color: rgba(0, 0, 255, 1)">this</span><span style="color: rgba(0, 0, 0, 1)">.rules) {
</span><span style="color: rgba(0, 0, 255, 1)">const</span> defaultValue = rule.<span style="color: rgba(0, 0, 255, 1)">params</span>[<span style="color: rgba(128, 0, 128, 1)">0</span><span style="color: rgba(0, 0, 0, 1)">]
</span><span style="color: rgba(0, 0, 255, 1)">if</span> (rule.name == <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">optional</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">) {
</span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> defaultValue
}
}
}
}
module.exports </span>=<span style="color: rgba(0, 0, 0, 1)"> {
Rule,
LinValidator
}</span></pre>
</div>
<p>util.js</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">const</span> jwt = require(<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">jsonwebtoken</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">)
</span><span style="color: rgba(0, 128, 0, 1)">/*</span><span style="color: rgba(0, 128, 0, 1)">**
*
</span><span style="color: rgba(0, 128, 0, 1)">*/</span>
<span style="color: rgba(0, 0, 255, 1)">const</span> findMembers =<span style="color: rgba(0, 0, 0, 1)"> function (instance, {
prefix,
specifiedType,
filter
}) {
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 递归函数</span>
<span style="color: rgba(0, 0, 0, 1)">function _find(instance) {
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">基线条件(跳出递归)</span>
<span style="color: rgba(0, 0, 255, 1)">if</span> (instance.__proto__ === <span style="color: rgba(0, 0, 255, 1)">null</span><span style="color: rgba(0, 0, 0, 1)">)
</span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> []
let names </span>=<span style="color: rgba(0, 0, 0, 1)"> Reflect.ownKeys(instance)
names </span>= names.filter((name) =><span style="color: rgba(0, 0, 0, 1)"> {
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 过滤掉不满足条件的属性或方法名</span>
<span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> _shouldKeep(name)
})
</span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> [...names, ..._find(instance.__proto__)]
}
function _shouldKeep(value) {
</span><span style="color: rgba(0, 0, 255, 1)">if</span><span style="color: rgba(0, 0, 0, 1)"> (filter) {
</span><span style="color: rgba(0, 0, 255, 1)">if</span><span style="color: rgba(0, 0, 0, 1)"> (filter(value)) {
</span><span style="color: rgba(0, 0, 255, 1)">return</span> <span style="color: rgba(0, 0, 255, 1)">true</span><span style="color: rgba(0, 0, 0, 1)">
}
}
</span><span style="color: rgba(0, 0, 255, 1)">if</span><span style="color: rgba(0, 0, 0, 1)"> (prefix)
</span><span style="color: rgba(0, 0, 255, 1)">if</span><span style="color: rgba(0, 0, 0, 1)"> (value.startsWith(prefix))
</span><span style="color: rgba(0, 0, 255, 1)">return</span> <span style="color: rgba(0, 0, 255, 1)">true</span>
<span style="color: rgba(0, 0, 255, 1)">if</span><span style="color: rgba(0, 0, 0, 1)"> (specifiedType)
</span><span style="color: rgba(0, 0, 255, 1)">if</span><span style="color: rgba(0, 0, 0, 1)"> (instance instanceof specifiedType)
</span><span style="color: rgba(0, 0, 255, 1)">return</span> <span style="color: rgba(0, 0, 255, 1)">true</span><span style="color: rgba(0, 0, 0, 1)">
}
</span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> _find(instance)
}
</span><span style="color: rgba(0, 0, 255, 1)">const</span> generateToken =<span style="color: rgba(0, 0, 0, 1)"> function(uid, scope){
</span><span style="color: rgba(0, 0, 255, 1)">const</span> secretKey = <span style="color: rgba(0, 0, 255, 1)">global</span><span style="color: rgba(0, 0, 0, 1)">.config.security.secretKey
</span><span style="color: rgba(0, 0, 255, 1)">const</span> expiresIn = <span style="color: rgba(0, 0, 255, 1)">global</span><span style="color: rgba(0, 0, 0, 1)">.config.security.expiresIn
</span><span style="color: rgba(0, 0, 255, 1)">const</span> token =<span style="color: rgba(0, 0, 0, 1)"> jwt.sign({
uid,
scope
},secretKey,{
expiresIn
})
</span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> token
}
module.exports </span>=<span style="color: rgba(0, 0, 0, 1)"> {
findMembers,
generateToken,
}</span></pre>
</div>
<p> (3)、定义自己的validator.js文件</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">const</span> { LinValidator, Rule } = require(<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">../../core/lin-validator</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">)
</span><span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> PositiveIntegerValidator extends LinValidator {
constructor () {
super()
</span><span style="color: rgba(0, 0, 255, 1)">this</span>.id =<span style="color: rgba(0, 0, 0, 1)"> [
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 校验的参数是:id,校验的函数名是:isInt,提示信息是:需要是正整数,其他条件是min: 1</span>
<span style="color: rgba(0, 0, 255, 1)">new</span> Rule(<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">isInt</span><span style="color: rgba(128, 0, 0, 1)">'</span>, <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">需要是正整数</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">, {
min: </span><span style="color: rgba(128, 0, 128, 1)">1</span><span style="color: rgba(0, 0, 0, 1)">
})
]
}
}
module.exports </span>=<span style="color: rgba(0, 0, 0, 1)"> {
PositiveIntegerValidator
}</span></pre>
</div>
<p> (4)、使用 </p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">const</span> { PositiveIntegerValidator } = require(<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">../../validators/validator</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">)
</span><span style="color: rgba(0, 0, 255, 1)">const</span> v = <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> PositiveIntegerValidator().validate(ctx)
<br>// 获取path里的值
console.log(v.</span><span style="color: rgba(0, 0, 255, 1)">get</span>(<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">path</span><span style="color: rgba(128, 0, 0, 1)">'</span>)) <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> path、query、body、header</span></pre>
</div>
<p>可以使用get()获取参数的值</p>
<p><img src="https://img2018.cnblogs.com/blog/1089823/201906/1089823-20190627103959938-38962046.png"></p>
<p> 13、俩种获取参数的方法</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">const</span> path = ctx.<span style="color: rgba(0, 0, 255, 1)">params</span>
<span style="color: rgba(0, 0, 255, 1)">const</span> query =<span style="color: rgba(0, 0, 0, 1)"> ctx.request.query
</span><span style="color: rgba(0, 0, 255, 1)">const</span> headers =<span style="color: rgba(0, 0, 0, 1)"> ctx.request.header
</span><span style="color: rgba(0, 0, 255, 1)">const</span> body = ctx.request.body</pre>
</div>
<p>和get()方法</p>
<p>推荐使用get()获取</p>
<p>原因:现在有个多层嵌套函数,如果用第一种方式,某一层没有值,会报错。而使用get(),会报空值</p>
<p>14、LinValidator校验器中的自定义规则函数 http://doc.cms.7yue.pro/lin/server/koa/validator.html#类校验</p>
<p> 我们把以<code>validate</code>开头的类方法称之为<strong>规则函数</strong>,我们会在校验的时候自动的调用 这些规则函数。</p>
<p> 规则函数是校验器中另一种用于对参数校验的方式,它比显示的 Rule 校验具有更加的灵活 性和可操作性。下面我们以一个小例子来深入理解规则函数:</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 0, 1)">validateConfirmPassword(data) {
</span><span style="color: rgba(0, 0, 255, 1)">if</span> (!data.body.password || !<span style="color: rgba(0, 0, 0, 1)">data.body.confirm_password) {
</span><span style="color: rgba(0, 0, 255, 1)">return</span> [<span style="color: rgba(0, 0, 255, 1)">false</span>, <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">两次输入的密码不一致,请重新输入</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">];
}
let ok </span>= data.body.password ===<span style="color: rgba(0, 0, 0, 1)"> data.body.confirm_password;
</span><span style="color: rgba(0, 0, 255, 1)">if</span><span style="color: rgba(0, 0, 0, 1)"> (ok) {
</span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> ok;
} </span><span style="color: rgba(0, 0, 255, 1)">else</span><span style="color: rgba(0, 0, 0, 1)"> {
</span><span style="color: rgba(0, 0, 255, 1)">return</span> [<span style="color: rgba(0, 0, 255, 1)">false</span>, <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">两次输入的密码不一致,请重新输入</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">];
}
}</span></pre>
</div>
<p>首先任何一个规则函数,满足以<code>validate</code>开头的类方法,除<code>validate()</code>这个函数外。都 会被带入一个重要的参数 <code>data</code>。data 是前端传入参数的容器,它的整体结构如下:</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">this</span>.data =<span style="color: rgba(0, 0, 0, 1)"> {
body: ctx.request.body, </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> body -> body</span>
query: ctx.request.query, <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> query -> query</span>
path: ctx.<span style="color: rgba(0, 0, 255, 1)">params</span>, <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> params -> path</span>
header: ctx.request.header <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> header -> header</span>
};</pre>
</div>
<p>请记住 data 参数是一个二级的嵌套对象,它的属性如下:</p>
<p> <img src="https://img2018.cnblogs.com/blog/1089823/201906/1089823-20190627153017420-988816074.png"></p>
<p> </p>
<p><code>data</code>是所有参数的原始数据,前端传入的参数会原封不动的装进 data。通过这个 data 我们可以很方便的对所有参数进行校验,如在<code>validateConfirmPassword</code>这个规则函数中 ,我们便对<code>data.body</code>中的<code>password</code>和<code>confirm_password</code>进行了联合校验。</p>
<p>我们通过对规则函数的返回值来判断,当前规则函数的校验是否通过。简单的理解,如果规 则返回<code>true</code>,则校验通过,如果返回<code>false</code>,则校验失败。但是校验失败的情况下,我们 需要返回一条错误信息,如:</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">return</span> [<span style="color: rgba(0, 0, 255, 1)">false</span>, <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">两次输入的密码不一致,请重新输入</span><span style="color: rgba(128, 0, 0, 1)">"</span>];</pre>
</div>
<p>表示规则函数校验失败,并且错误信息为<code>两次输入的密码不一致,请重新输入</code>。</p>
<p>15、Koa2中使用sequelize创建数据表 </p>
<p> 文档: https://itbilu.com/nodejs/npm/VkYIaRPz-.html#api-instance-createSchema</p>
<p> 操作mysql</p>
<p> 需要安装sequelize和mysql2</p>
<p> </p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">const</span> { Sequelize } = require(<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">sequelize</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">)
</span><span style="color: rgba(0, 0, 255, 1)">const</span><span style="color: rgba(0, 0, 0, 1)"> {
dbName,
host,
port,
username,
password
} </span>= require(<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">../config/config</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">).database
</span><span style="color: rgba(0, 0, 255, 1)">const</span> sequelize = <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> Sequelize(dbName, username, password, {
dialect:</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">mysql</span><span style="color: rgba(128, 0, 0, 1)">'</span>, <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 数据库类型</span>
<span style="color: rgba(0, 0, 0, 1)">host,
port,
logging: </span><span style="color: rgba(0, 0, 255, 1)">true</span>, <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 记录操作的sql语句</span>
timezone: <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">+08:00</span><span style="color: rgba(128, 0, 0, 1)">'</span> <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 默认的时间会比正常时间慢8小时</span>
})</pre>
</div>
<p> </p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 加了这个,才能把定义的模型同步到数据库中</span>
<span style="color: rgba(0, 0, 0, 1)">sequelize.sync({
force: </span><span style="color: rgba(0, 0, 255, 1)">false</span> <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> true会自动运行,通过定义的model修改数据库中的表</span>
})</pre>
</div>
<pre><span>force为true的时候,如果我们修改models中定义的属性值,就会自动同步到数据库表(会清空数据库表并重建),我们一般设置为false</span></pre>
<p> </p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 0, 1)">News.init({
id: {
type: Sequelize.INTEGER,
primaryKey: </span><span style="color: rgba(0, 0, 255, 1)">true</span>, <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 键</span>
autoIncrement: <span style="color: rgba(0, 0, 255, 1)">true</span> <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 自增长</span>
<span style="color: rgba(0, 0, 0, 1)">},
title: Sequelize.STRING,
summary: Sequelize.STRING
}, {
sequelize,
tableName: </span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">news</span><span style="color: rgba(128, 0, 0, 1)">'</span> <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 自定义数据库表名</span>
})</pre>
</div>
<p>mode中定义好数据库表的字段以后,需要在其他js文件引入这个model文件,Sequelize才会操作数据库表</p>
<p> </p>
<p> </p>
<p>16、使用lin-validator-v2,new RegisterValidator()前面加await?</p>
<div class="cnblogs_code">
<pre>router.post(<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">/register</span><span style="color: rgba(128, 0, 0, 1)">'</span>, <span style="color: rgba(0, 0, 255, 1)">async</span> (ctx) =><span style="color: rgba(0, 0, 0, 1)"> {
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 为何要在new RegisterValidator()前面加await,而且使用lin-validator-v2?</span>
<span style="color: rgba(0, 128, 0, 1)">/*</span><span style="color: rgba(0, 128, 0, 1)">*
* 因为RegisterValidator里validateEmail方法中的User.findOne是一个Promise异步操作,
* 不加await的话,无法阻止错误,还是会执行后面的代码,引起系统报错
</span><span style="color: rgba(0, 128, 0, 1)">*/</span>
<span style="color: rgba(0, 0, 255, 1)">const</span> v = <span style="color: rgba(0, 0, 255, 1)">await</span> <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> RegisterValidator().validate(ctx)
</span><span style="color: rgba(0, 0, 255, 1)">const</span> user =<span style="color: rgba(0, 0, 0, 1)"> {
email: v.</span><span style="color: rgba(0, 0, 255, 1)">get</span>(<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">body.email</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">),
password: v.</span><span style="color: rgba(0, 0, 255, 1)">get</span>(<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">body.password1</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">),
nickname: v.</span><span style="color: rgba(0, 0, 255, 1)">get</span>(<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">body.nickname</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">)
}
User.create(user)
})</span></pre>
</div>
<p> 17、在node项目中的请求,每一个请求都要new一次validate,为什么一定要这样做,有没有其他的写法?</p>
<div class="cnblogs_code">
<pre>router.post(<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">/register</span><span style="color: rgba(128, 0, 0, 1)">'</span>, <span style="color: rgba(0, 0, 255, 1)">async</span> (ctx) =><span style="color: rgba(0, 0, 0, 1)"> {
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 为何要在new RegisterValidator()前面加await,而且使用lin-validator-v2?</span>
<span style="color: rgba(0, 128, 0, 1)">/*</span><span style="color: rgba(0, 128, 0, 1)">*
* 因为RegisterValidator里validateEmail方法中的User.findOne是一个Promise异步操作,
* 不加await的话,无法阻止错误,还是会执行后面的代码,引起系统报错
</span><span style="color: rgba(0, 128, 0, 1)">*/</span>
<span style="color: rgba(255, 153, 0, 1)"> const v = await new RegisterValidator().validate(ctx)
</span><span style="color: rgba(0, 0, 255, 1)">const</span> user =<span style="color: rgba(0, 0, 0, 1)"> {
email: v.</span><span style="color: rgba(0, 0, 255, 1)">get</span>(<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">body.email</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">),
password: v.</span><span style="color: rgba(0, 0, 255, 1)">get</span>(<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">body.password1</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">),
nickname: v.</span><span style="color: rgba(0, 0, 255, 1)">get</span>(<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">body.nickname</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">)
}
User.create(user)
})</span></pre>
</div>
<p>就有另一种写法,就是把validate当成中间件</p>
<div class="cnblogs_code">
<pre>router.post(<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">/register</span><span style="color: rgba(128, 0, 0, 1)">'</span>,<span style="color: rgba(255, 153, 0, 1)">new RegisterValidator()</span>, <span style="color: rgba(0, 0, 255, 1)">async</span> (ctx) =><span style="color: rgba(0, 0, 0, 1)"> {
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 为何要在new RegisterValidator()前面加await,而且使用lin-validator-v2?</span>
<span style="color: rgba(0, 128, 0, 1)">/*</span><span style="color: rgba(0, 128, 0, 1)">*
* 因为RegisterValidator里validateEmail方法中的User.findOne是一个Promise异步操作,
* 不加await的话,无法阻止错误,还是会执行后面的代码,引起系统报错
</span><span style="color: rgba(0, 128, 0, 1)">*/</span>
<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> const v = await new RegisterValidator().validate(ctx)</span>
<span style="color: rgba(0, 0, 255, 1)">const</span> user =<span style="color: rgba(0, 0, 0, 1)"> {
email: v.</span><span style="color: rgba(0, 0, 255, 1)">get</span>(<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">body.email</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">),
password: v.</span><span style="color: rgba(0, 0, 255, 1)">get</span>(<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">body.password1</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">),
nickname: v.</span><span style="color: rgba(0, 0, 255, 1)">get</span>(<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">body.nickname</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">)
}
User.create(user)
})</span></pre>
</div>
<p>但是这有个很大的问题,node中的中间件只new一次,我们的validate是class,在class保存属性的时候回出错</p>
<p>比如validate.a = 1,后面改成validate.a = 2,这样判断就会出错</p>
<p>但是如果我们在每个请求中New一次validate,这就没问题</p>
<p>这个涉及到面向对象的知识,使用中间件的方式,只new一次,生成一个对象,这样多个地方会改变里面的值</p>
<p>如果是每个请求new一次,那么就生成单独的对象,改变属性值的时候,不会影响其他对象里的值</p>
<p> </p>
<p>18、使用bcryptjs加密</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">const</span> bcrypt = require(<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">bcryptjs</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">)
</span><span style="color: rgba(0, 0, 255, 1)">const</span> salt = bcrypt.genSaltSync(<span style="color: rgba(128, 0, 128, 1)">10</span><span style="color: rgba(0, 0, 0, 1)">)
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 10是位数,标识计算机计算的时候用多久,不宜太大</span>
<span style="color: rgba(0, 0, 255, 1)">const</span> psw = bcrypt.hashSync(v.<span style="color: rgba(0, 0, 255, 1)">get</span>(<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">body.password1</span><span style="color: rgba(128, 0, 0, 1)">'</span>), salt)</pre>
</div>
<p>这样的写法每个有password的地方都要这样写,有另一种更好的</p>
<p>在定义模型的文件里,使用set方法进行监控</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 0, 1)">password: {
type: Sequelize.STRING,
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 观察者模式</span>
<span style="color: rgba(0, 0, 255, 1)">set</span><span style="color: rgba(0, 0, 0, 1)"> (val) {
</span><span style="color: rgba(0, 0, 255, 1)">const</span> salt = bcrypt.genSaltSync(<span style="color: rgba(128, 0, 128, 1)">10</span><span style="color: rgba(0, 0, 0, 1)">)
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 10是位数,标识计算机计算的时候用多久,不宜太大</span>
<span style="color: rgba(0, 0, 255, 1)">const</span> psw =<span style="color: rgba(0, 0, 0, 1)"> bcrypt.hashSync(val, salt)
</span><span style="color: rgba(0, 0, 255, 1)">this</span>.setDataValue(<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">password</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">, psw)
}
}</span></pre>
</div>
<p> 使用bcryptjs中的compareSync验证转入的密码和数据库中加密的密码是否一致</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">const</span> correct = bcrypt.compareSync(plainPassword, User.password)</pre>
</div>
<p> </p>
<p>19、success效果,执行成功以后返回提示信息</p>
<p> 第一种方案:</p>
<div class="cnblogs_code">
<pre>ctx.body =<span style="color: rgba(0, 0, 0, 1)"> {
msg: </span><span style="color: rgba(128, 0, 0, 1)">''</span><span style="color: rgba(0, 0, 0, 1)">,
code: </span><span style="color: rgba(128, 0, 0, 1)">''</span><span style="color: rgba(0, 0, 0, 1)">
}</span></pre>
</div>
<p>使用ctx.body返回成功信息</p>
<p>第二种方案:</p>
<p>把success包装成exception,返回的时候,传递success的msg和code</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> exception.js</span>
<span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> Success extends HttpException {
constructor(msg, errorCode) {
super()
</span><span style="color: rgba(0, 0, 255, 1)">this</span>.code = <span style="color: rgba(128, 0, 128, 1)">201</span>
<span style="color: rgba(0, 0, 255, 1)">this</span>.msg = msg || <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">ok</span><span style="color: rgba(128, 0, 0, 1)">'</span>
<span style="color: rgba(0, 0, 255, 1)">this</span>.errorCode = errorCode || <span style="color: rgba(128, 0, 128, 1)">0</span><span style="color: rgba(0, 0, 0, 1)">
}
}
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> heaper.hs</span>
<span style="color: rgba(0, 0, 0, 1)">
function success(msg, errorCode) {
</span><span style="color: rgba(0, 0, 255, 1)">throw</span> <span style="color: rgba(0, 0, 255, 1)">new</span> <span style="color: rgba(0, 0, 255, 1)">global</span><span style="color: rgba(0, 0, 0, 1)">.errs.Success(msg, errorCode)
}
module.exports </span>=<span style="color: rgba(0, 0, 0, 1)"> {
success
}</span></pre>
</div>
<p>在使用的地方引入,直接success()</p>
<p> </p>
<p>20、权限的判断</p>
<p>我们可以给不同的角色设置不同的值,比如user(普通用户)为8,admin(管理员)为16,默认的权限值为1,每个接口可以设置不同的权限值。</p>
<p>登录的时候,把用户的权限通过token传递到前端。前端请求接口的时候,通过token判断当前用户的权限,如果比接口需要的权限值大,那就说明可以访问,不然就是权限不足</p>
<p>auth.js</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">const</span> basicAuth = require(<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">basic-auth</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">)
</span><span style="color: rgba(0, 0, 255, 1)">const</span> jwt = require(<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">jsonwebtoken</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">)
</span><span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> Auth {
constructor (level) {
</span><span style="color: rgba(0, 0, 255, 1)">this</span>.level = level || <span style="color: rgba(128, 0, 128, 1)">1</span> <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 设置默认的权限值,可以由接口自定义</span>
Auth.USER = <span style="color: rgba(128, 0, 128, 1)">8</span><span style="color: rgba(0, 0, 0, 1)">
Auth.ADMIN </span>= <span style="color: rgba(128, 0, 128, 1)">16</span><span style="color: rgba(0, 0, 0, 1)">
Auth.SUPER_ADMIN </span>= <span style="color: rgba(128, 0, 128, 1)">32</span><span style="color: rgba(0, 0, 0, 1)">
}
</span><span style="color: rgba(0, 0, 255, 1)">get</span><span style="color: rgba(0, 0, 0, 1)"> m () {
</span><span style="color: rgba(0, 0, 255, 1)">return</span> <span style="color: rgba(0, 0, 255, 1)">async</span> (ctx, next) =><span style="color: rgba(0, 0, 0, 1)"> {
</span><span style="color: rgba(0, 0, 255, 1)">const</span> userToken =<span style="color: rgba(0, 0, 0, 1)"> basicAuth(ctx.req)
let errMsg </span>= <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">token不合法</span><span style="color: rgba(128, 0, 0, 1)">'</span>
<span style="color: rgba(0, 0, 255, 1)">if</span> (!userToken || !<span style="color: rgba(0, 0, 0, 1)">userToken.name) {
</span><span style="color: rgba(0, 0, 255, 1)">throw</span> <span style="color: rgba(0, 0, 255, 1)">new</span> <span style="color: rgba(0, 0, 255, 1)">global</span><span style="color: rgba(0, 0, 0, 1)">.errs.Forbbiden(errMsg)
}
</span><span style="color: rgba(0, 0, 255, 1)">try</span><span style="color: rgba(0, 0, 0, 1)"> {
</span><span style="color: rgba(0, 0, 255, 1)">var</span> decode = jwt.verify(userToken.name, <span style="color: rgba(0, 0, 255, 1)">global</span><span style="color: rgba(0, 0, 0, 1)">.config.security.secretKey)
} </span><span style="color: rgba(0, 0, 255, 1)">catch</span><span style="color: rgba(0, 0, 0, 1)"> (error) {
</span><span style="color: rgba(0, 0, 255, 1)">if</span> (error.name === <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">TokenExpiredError</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">){
errMsg </span>= <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">token已过期</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">
}
</span><span style="color: rgba(0, 0, 255, 1)">throw</span> <span style="color: rgba(0, 0, 255, 1)">new</span> <span style="color: rgba(0, 0, 255, 1)">global</span><span style="color: rgba(0, 0, 0, 1)">.errs.Forbbiden(errMsg)
}
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 判断用户的权限是否比接口需要的权限小</span>
<span style="color: rgba(0, 0, 255, 1)">if</span>(decode.scope < <span style="color: rgba(0, 0, 255, 1)">this</span><span style="color: rgba(0, 0, 0, 1)">.level){
errMsg </span>= <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">权限不足</span><span style="color: rgba(128, 0, 0, 1)">'</span>
<span style="color: rgba(0, 0, 255, 1)">throw</span> <span style="color: rgba(0, 0, 255, 1)">new</span> <span style="color: rgba(0, 0, 255, 1)">global</span><span style="color: rgba(0, 0, 0, 1)">.errs.Forbbiden(errMsg)
}
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 获取token里的uid,scope</span>
ctx.auth =<span style="color: rgba(0, 0, 0, 1)"> {
uid: decode.uid,
scope: decode.scope
}
</span><span style="color: rgba(0, 0, 255, 1)">await</span><span style="color: rgba(0, 0, 0, 1)"> next()
}
}
}
module.exports </span>=<span style="color: rgba(0, 0, 0, 1)"> {
Auth
}</span></pre>
</div>
<p>classic.js</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">const</span> { Auth } = require(<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">../../../middlewares/auth</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">)
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> auth也是一个中间件,一定要写在后面的中间件前面,这样才能阻止后面的中间件
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 可以在new Auth()里传递值,确定访问当前接口需要什么权限</span>
router.<span style="color: rgba(0, 0, 255, 1)">get</span>(<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">/latest</span><span style="color: rgba(128, 0, 0, 1)">'</span>, <span style="color: rgba(0, 0, 255, 1)">new</span> Auth(<span style="color: rgba(128, 0, 128, 1)">2</span>).m, <span style="color: rgba(0, 0, 255, 1)">async</span> (ctx, next) =><span style="color: rgba(0, 0, 0, 1)"> {
</span><span style="color: rgba(0, 0, 255, 1)">const</span> v = <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> PositiveIntegerValidator().validate(ctx)
</span><span style="color: rgba(0, 0, 255, 1)">const</span> id = <span style="color: rgba(0, 0, 255, 1)">await</span> v.<span style="color: rgba(0, 0, 255, 1)">get</span>(<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">path.id</span><span style="color: rgba(128, 0, 0, 1)">'</span>, parsed = <span style="color: rgba(0, 0, 255, 1)">false</span>) <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> path、query、body、header</span>
ctx.body =<span style="color: rgba(0, 0, 0, 1)"> {
msg: </span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">success</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">,
id: v.</span><span style="color: rgba(0, 0, 255, 1)">get</span>(<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">path.id</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">)
}
})</span></pre>
</div>
<p> </p>
<p>21、微信小程序从登录到获取token一系列操作</p>
<p>https://developers.weixin.qq.com/miniprogram/dev/framework/open-ability/login.html</p>
<p>微信登录后调用wx.login方法,获取临时凭证code,传递给后端服务器</p>
<p>后端服务器调用 auth.code2Session接口,换取 <strong>用户唯一标识 OpenID</strong> 和 <strong>会话密钥 session_key</strong>。</p>
<p>使用OpenID生成token,返回给前端</p>
<p> </p>
<p>22、<span class="post_title_content">获取openid每次都会返回errcode:40013 错误</span></p>
<p><span class="post_title_content">检查appId的值</span></p>
<p><span class="post_title_content">23、访问Node项目的时候会突然奔溃,并报错ctx.onerror is not a function 地址:https://segmentfault.com/q/1010000009716118</span></p>
<p><span class="post_title_content">原因是:</span>koa-bodyparser不对</p>
<p>正确应该是:</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">const</span> parser = require(<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">koa-bodyparser</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">)
app.use(parser())</span></pre>
</div>
<p> 24、使用了Sequelize创建的模型,如果要给模型添加额外的属性,就需要使用setDataValue</p>
<div class="cnblogs_code">
<pre>art.setDataValue(<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">index</span><span style="color: rgba(128, 0, 0, 1)">'</span>, flow.index)</pre>
</div>
<p>给art模型添加index属性并赋值</p>
<p>25、每次引入数据的时候,都会写很长的路径,为了方便,我们可以起别名,node里的别名是写在package.json里的</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">_moduleAliases</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">:{
</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">@root</span><span style="color: rgba(128, 0, 0, 1)">"</span>:<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">.</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">,
</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">@models</span><span style="color: rgba(128, 0, 0, 1)">"</span>:<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">app/models</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">,
</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">@validator</span><span style="color: rgba(128, 0, 0, 1)">"</span>:<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">app/validators/validator.js</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">
}</span></pre>
</div>
<p>使用</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">const</span><span style="color: rgba(0, 0, 0, 1)"> {
Favor
} </span>= require(<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">@models/favor</span><span style="color: rgba(128, 0, 0, 1)">'</span>)</pre>
</div>
<p>不过我在使用中发现,一直在报错,无法找到路径,不知道为什么</p>
<p>26。我们在查询表的时候,会返回表中所有的字段,有时候一些字段不需要,就要过滤掉,这是我们用Sequelize中的Scopes</p>
<p>https://sequelize.org/master/manual/scopes.html</p>
<p>在db表里统一进行设置</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">const</span> sequelize = <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> Sequelize(dbName, username, password, {
dialect:</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">mysql</span><span style="color: rgba(128, 0, 0, 1)">'</span>, <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 数据库类型</span>
<span style="color: rgba(0, 0, 0, 1)">host,
port,
logging: </span><span style="color: rgba(0, 0, 255, 1)">true</span>, <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 记录操作的sql语句</span>
timezone: <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">+08:00</span><span style="color: rgba(128, 0, 0, 1)">'</span>, <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 默认的时间会比正常时间慢8小时</span>
<span style="color: rgba(0, 0, 0, 1)">define: {
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> timestamps: false </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 设置为false,就不会生成createdAt和updateAt了</span>
timestamps: <span style="color: rgba(0, 0, 255, 1)">true</span>, <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 管理 createdAt和updateAt</span>
paranoid: <span style="color: rgba(0, 0, 255, 1)">true</span>, <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 管理deletedAt</span>
createdAt: <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">created_at</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">,
updatedAt: </span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">updated_at</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">,
deletedAt: </span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">deleted_at</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">,
underscored: </span><span style="color: rgba(0, 0, 255, 1)">true</span>, <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 把驼峰转换成下划线</span>
<span style="color: rgba(0, 0, 0, 1)"> scopes: {
bh: {
attributes:{
exclude:[</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">updated_at</span><span style="color: rgba(128, 0, 0, 1)">'</span>,<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">deleted_at</span><span style="color: rgba(128, 0, 0, 1)">'</span>,<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">created_at</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">]
}
}
}
}
})</span></pre>
</div>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 0, 1)">scopes: {
bh: {
attributes:{
exclude:[</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">updated_at</span><span style="color: rgba(128, 0, 0, 1)">'</span>,<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">deleted_at</span><span style="color: rgba(128, 0, 0, 1)">'</span>,<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">created_at</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">]
}
}
}</span></pre>
</div>
<p>在scopes里我们可以定义多个函数,现在定义的是bh,exclude表示过滤掉这些字段</p>
<p> </p>
<p>使用的时候</p>
<div class="cnblogs_code">
<pre>art = <span style="color: rgba(0, 0, 255, 1)">await</span> Movie.scope(<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">bh</span><span style="color: rgba(128, 0, 0, 1)">'</span>).findOne(finder)</pre>
</div>
<p>在调用Sequelize自带的查询方法钱调用scope(),并传入之前定义好的函数名</p>
<p>备注:scopes也可以在每个表的模型文件中定义</p><br><br>
来源:https://www.cnblogs.com/zhaobao1830/p/11026864.html
頁:
[1]