常见的路由范式,拿产品product举例:
产品列表页: /product
产品详情页: /product/:id
产品编辑新增: /product/edit/:id? 有id表示编辑,无id表示新增
产品删除: /product/delete/:id
比较简单有效,无多余单词,以上供参考。
相对的根据大功能模块扩展,比如文章模块和商城模块,分别在以上范式基础上,加商定的模块前缀:/article 和 /mall
路由一般情况下应可以逐级追溯:例如 /mall/product/:id/comment
第一级:/mall 商城模块主页
第二级:/mall/product 商城产品列表
第三级: /mall/product/:id 某产品详情
第四级: /mall/product/:id/comment 该产品下的评论列表
以上可以作为设计路由时遵循的思路。
继续阅读~
参与评论~
在开发maty.js时,遇到一个数组任务,数组项是内部异步执行的函数,期望是同步依次执行每项函数,每项函数执行完本身的异步任务后,继续下一项。
刚开始单纯使用map来循环执行,并且await每项函数。如下所示:
starters.map(async (fn, i)=> {
console.log('++++++++++: ', i)
await fn(ctx);
});
结果是依次先输出了索引i,而不是阻塞每次循环,按期望执行。
搬出Google大法,在https://blog.lavrton.com/javascript-loops-how-to-handle-async-await-6252dd3c795中得到解决办法,对在 for…of 循环语法中使用await是有效的。
for (const fn of starters) {
await fn(ctx);
}
同时文章中指出使用Promise.all,是无法解决当前问题的,因为all方法是并行运行的。很奇怪为什么没有串行执行的原生方法。
继续阅读~
参与评论~
nodejs transform可以用于对stream的数据修改定制,并返回修改后的stream。对于其用法,官方文档其实并不好理解,找到两篇文章可以帮助理解:
1、http://fred-zone.blogspot.com/2017/09/nodejs-transform-stream.html 说明的比较浅显易懂。
2、https://juejin.im/post/5a4a377151882546f00a68c9 涉及比较多的内容和例子。
有这两篇就够了。
继续阅读~
参与评论~
完整的报错信息如下:
{ Error: socket hang up
at createHangUpError (_http_client.js:330:15)
at Socket.socketOnEnd (_http_client.js:423:23)
at Socket.emit (events.js:164:20)
at endReadableNT (_stream_readable.js:1062:12)
at process._tickCallback (internal/process/next_tick.js:152:19) code: 'ECONNRESET' }
(node:29975) UnhandledPromiseRejectionWarning: Error: socket hang up
at createHangUpError (_http_client.js:330:15)
at Socket.socketOnEnd (_http_client.js:423:23)
at Socket.emit (events.js:164:20)
at endReadableNT (_stream_readable.js:1062:12)
at process._tickCallback (internal/process/next_tick.js:152:19)
(node:29975) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). (rejection id: 1)
(node:29975) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.
继续阅读~
参与评论~
nginx源码安装时,使用如下配置开启https和tsl支持。依赖系统中安装openssl。
./configure --prefix=/usr/local/nginx --with-http_ssl_module --with-http_v2_module --with-http_gzip_static_module --with-openssl-opt="enable-tlsext"
继续阅读~
参与评论~
对于大部分的右手习惯用户来讲,有一个事实:眼睛在左,右手在右。反映到交互UI上即:视觉在左,操作在右。
从符合人体工程学的角度想,这是否代表了一种设计原则呢?而且是非常朴素易懂的原则。
继续阅读~
参与评论~
最近在pm2.log中看见如下错误导致无法启动服务:
path.js:1144
cwd = process.cwd();
^
Error: ENOENT: no such file or directory, uv_cwd
at Error (native)
at Object.resolve (path.js:1144:25)
at Function.Module._resolveLookupPaths (module.js:361:17)
at Function.Module._resolveFilename (module.js:431:31)
at Function.Module._load (module.js:388:25)
at Module.require (module.js:468:17)
at require (internal/module.js:20:19)
at Object. (/usr/lib/node_modules/pm2/lib/ProcessContainer.js:12:15)
at Module._compile (module.js:541:32)
at Object.Module._extensions..js (module.js:550:10)
于是google之,在https://github.com/Unitech/pm2/issues/2057找到方法解决,记录如下:
首先导致这个错误是因为pm2最早启动的目录被删除了(删除后重建同名目录也是无用的)。
什么叫最早启动的目录呢?就是在命令行下第一次执行pm2时所在的目录,比如新装系统,在 /home/deploy 下第一次执行 pm2命令,那么 /home/deploy 就是最早启动的目录。再比如杀掉pm2进程后,再次在某个目录下执行了pm2命令,那这个目录也是最早启动的目录。
理解了最早启动的目录,那么当pm2启动后,把该目录删除过一次,则再次用pm2去启动node服务时就会报以上错误。
pm2 issues-2057中也有人指出了验证方法,如下:
- 先找到pm2的进程pid:
ps ax | grep PM2
- 然后查询该进程执行时所在的目录(用上一步得到的pid替换下面命令的PM2_PID)
ls -l /proc/PM2_PID/cwd
- 最后根据结果,如下的(deleted)标注,就说明该目录被删除过。
$ ls -l /proc/24016/cwd
lrwxrwxrwx 1 root root 0 Feb 4 17:04 /proc/24016/cwd -> /home/nodejs/deploy(deleted)
验证原因后,解决方法就是重新在另外一个安全一些的目录重启pm2进程。
先用pm2 kill命令杀掉pm2进程,然后 cd ~ 到home目录,执行 pm2 -v 命令,这样就在一个相对安全的目录启动了pm2。最后再去部署node服务就可以了。
继续阅读~
参与评论~
Mongodb线上真实事故案例 https://cnodejs.org/topic/55c97a997a5d91fa63fe9ce7
继续阅读~
参与评论~
场景是这样的,有一个自定义的tag,用到了_ctx.__require,代码片段如下:
var s = (ignore ? ' try {\n' : '') +
'var _compiler = _ctx.__require("' + normalize + '");' +
'_output += _compiler(' +
((onlyCtx && w) ? w : (!w ? '_ctx' : '_utils.extend({}, _ctx, ' + w + ')')) +
');\n' +
(ignore ? '} catch (e) {}\n' : '');
然后之前使用过设置模板内变量的方法:
swig.setDefaults({
locals: {
'xxx': '11'
}
});
一直相安无事,最近改了逻辑,去掉了setDefaults locals,结果一刷新页面(该页面使用了上述自定义tag),页面就报错:
TypeError: _ctx.__require is not a function
并且只是重启node服务后首次刷新页面才会出现,再次刷新就不会出现这个错误。。。搞得莫名其妙的,再次把locals set一下,就不会出现这种报错。 更奇特的是,locals不能是一个空对象{}, 必须至少有一对key:value。
暂时还不明确具体原因。
继续阅读~
参与评论~