关于node.js:Nodejs-基础学习记录四

3. 第三方模块3.1 什么是第三方模块他人写好的、具备特定性能的、咱们能间接应用的模块即第三方模块,因为第三方模块通常都是由多个文件组成并且被搁置在一个文件夹中,所以又名包。 第三方模块有两种存在模式: 以js文件的模式存在,提供实现我的项目具体性能的API接口。以命令行工具模式存在,辅助我的项目开发3.2 获取第三方模块npmjs.com:第三方模块的存储和散发仓库 npm (node package manager) : node的第三方模块管理工具 下载:npm install 模块名称卸载:npm unintall package 模块名称全局装置与本地装置 命令行工具:全局装置库文件:本地装置3.3 第三方模块 nodemonnodemon是一个命令行工具,用以辅助我的项目开发。在Node.js中,每次批改文件都要在命令行工具中从新执行该文件,十分繁琐。 应用步骤 应用npm install nodemon –g 下载它在命令行工具中用nodemon命令代替node命令执行文件3.4 第三方模块 nrmnrm ( npm registry manager ):npm下载地址切换工具npm默认的下载地址在国外,国内下载速度慢 应用步骤 应用npm install nrm –g 下载它查问可用下载地址列表 nrm ls切换npm下载地址 nrm use 下载地址名称3.5 第三方模块 Gulp基于node平台开发的前端构建工具将机械化操作编写成工作, 想要执行机械化操作时执行一个命令行命令工作就能主动执行了用机器代替手工,进步开发效率。 3.6 Gulp能做什么我的项目上线,HTML、CSS、JS文件压缩合并语法转换(es6、less ...)公共文件抽离批改文件浏览器主动刷新3.7 Gulp应用应用npm install gulp下载gulp库文件在我的项目根目录下建设gulpfile.js文件重构我的项目的文件夹构造 src目录搁置源代码文件 dist目录搁置构建后文件在gulpfile.js文件中编写工作.在命令行工具中执行gulp工作3.8 Gulp中提供的办法gulp.src():获取工作要解决的文件gulp.dest():输入文件gulp.task():建设gulp工作gulp.watch():监控文件的变动 const gulp = require('gulp'); // 应用gulp.task()办法建设工作 gulp.task('first', () => { // 获取要解决的文件 gulp.src('./src/css/base.css') // 将解决后的文件输入到dist目录 .pipe(gulp.dest('./dist/css')); });3.9 Gulp插件gulp-htmlmin :html文件压缩gulp-csso :压缩cssgulp-babel :JavaScript语法转化gulp-less: less语法转化gulp-uglify :压缩混同JavaScriptgulp-file-include 公共文件蕴含browsersync 浏览器实时同步

April 2, 2021 · 1 min · jiezi

关于node.js:华为应用市场AppGallery-Connect正式推出全新LOGO

华为利用市场AppGallery Connect(简称AGC)正式推出全新Logo,新Logo的设计灵感源于编码中的符号<>,两个括号严密联结成一个正方形,寓意华为利用市场AGC与开发者深度单干,携手打造翻新利用,凸显了华为利用市场AGC不仅仅是利用散发服务平台,更是开发者利用翻新路上互为亲密合作伙伴的含意。 AppGallery Connect的Slogan是加载翻新源能源(Empowering Creativity),面向寰球开发者提供涵盖“创意-开发-散发-经营-剖析”的利用全生命周期服务,反对Android、iOS、Web、快利用多个平台。AGC关注开发者的生产和经营,立足于践行利用开发和经营效率的晋升,帮忙开发者取得用户及支出的规模增长,减速利用翻新和商业胜利的同时,为寰球消费者带来更美妙的数字生存体验。 截至2020年12月底,AGC为170多个国家和地区的230万开发者,累计凋谢了87项服务。在所有服务的示例中,认证服务帮忙开发者在开发效率上晋升了80%,近程配置帮忙利用的月活晋升10%,App Bundle利用散发服务使得利用的装置成功率进步了4%,此外还有更多的服务帮忙开发者获得了不同水平的胜利。 为了减速生态共建共赢,AGC还提供了多维度的赋能和激励措施,包含DIGIX翻新工作室、耀星激励打算、AGC研习社等。翻新工作室联合华为凋谢软件和硬件劣势能力,凋谢面向未来的新技术,联结搭档一起翻新利用。“耀星·AppGallery Connect打算”已全面反对接入服务的翻新利用,开发者将有机会取得线上推广资源,华为线下营销平台推广资源以及华为云基础设施的优惠资源,激励开发者减速利用翻新。 AGC研习社提供了丰盛的线上赋能课程,心愿开发者可能更好地利用AGC服务,在商业胜利路上,可能起到真正意义上的助力作用。同时,AGC研习社还在多个城市举办线下开发者沙龙,全面解读AGC凋谢的服务能力,分享搭档们的成功经验,促成开发者之间的互动和交换。将来,AGC将持续携手开发者独特推动科技翻新,共享翻新成绩,为构建利用翻新生态提供更无力的撑持。

March 31, 2021 · 1 min · jiezi

关于node.js:CabloyJS-470支持通用静态渲染机制

<4.7.0CabloyJS是一款前后端拆散的框架,前端采纳Vue + Framework7实现了SPA的模式。为了解决SEO优化的问题,并晋升拜访性能,专门开发了一个CMS模块,采纳动静联合(即JAMStack模式),能够疾速构建企业网站、博客、技术文档、社区等Web利用 从而,能够了解为,CMS模块渲染进去的动态网站是Web前端,CabloyJS主体框架作为治理后端 >=4.7.0CabloyJS 4.7.0对CMS渲染机制进行了进一步提炼,造成通用的渲染机制。也就是说,任何原子类型(业务数据)均能够依据业务的理论需要,便捷的配置动态渲染机制,比方商品、订单,等等 具体实现形式,请参考CabloyJS内置的测试模块:test-party 相干链接官网: https://cabloy.com/GitHub: https://github.com/zhennann/cabloy

March 31, 2021 · 1 min · jiezi

关于node.js:web前端常用的五种方式搭建本地静态html页面服务器

形式一:live-serverlive-server是一款npm工具,能够在我的项目目录启动一个node服务,而后间接在浏览器中预览,并且主动全局监听实时更新。 两种装置形式: 全局装置 npm i live-server -g本地装置 npm i live-server --save-dev间接应用live-server首先在我的项目下npm初始化:npm init -y; 而后能够抉择全局装置或者本地装置live-server,而后在package.json的scripts属性中增加如下代码: "scripts": { "server": "live-server ./ --port=8181 --host=localhost --proxy=/api:http://www.abc.com/api/"}中包含了代理设置proxy。 而后npm run server执行下就会主动关上以后工程,默认指向index.html页面。 应用node首先本地装置live-server,执行如下指令: npm i live-server --save-dev而后在该我的项目下新建一个build.js,代码如下: var liveServer = require("live-server");var params = { port: 8181, host: "localhost", open: true, file: "index.html", wait: 1000, logLevel: 2, proxy: [['/api','http://www.abc.com/api/']]};liveServer.start(params);最初在package.json的scripts下增加如下代码: "scripts": { "dev": "node build.js"}最初执行npm run dev就启动了本地动态页面,门路即是:http://localhost:8081/ 具体参考地址:https://www.npmjs.com/package/live-server 形式二:http-server全局装置http-server npm i -g http-server用法: http-server [path] [options]其中的path默认指向工程门路下的./public,如果不存在那么应用./。 options就是常见的配置,比方端口、代理地址等,罕用配置: -p or --port Port to use (defaults to 8080). It will also read from process.env.PORT. (设置端口)-a Address to use (defaults to 0.0.0.0) (设置拜访地址)-P or --proxy Proxies all requests which can't be resolved locally to the given url. e.g.: -P http://someurl.com(设置代理地址)-o [path] Open browser window after starting the server. Optionally provide a URL path to open. e.g.: -o /other/dir/ (默认关上浏览器)cmd进入动态目录工程,可执行如下操作: ...

March 30, 2021 · 4 min · jiezi

关于github:除了wordpress你还可以试试这款开源cms

 大家好,我是为宽广程序员兄弟操碎了心的小编,每天举荐一个小工具/源码,装满你的收藏夹,每天分享一个小技巧,让你轻松节俭开发效率,实现不加班不熬夜不掉头发,是我的指标! 目前市面上有很多内容管理系统,都是以php为根底编写的,而明天小编举荐的一款开源CMS零碎则是基于Nodejs+eggjs+mongodb编写的,只须要根本的前端开发教训和大量的js,就很容易上手。 设计思维很简略,以简洁为准则,构造清晰,较目前一些开源的cms来说,更易于拓展,特地适宜前端开发工程师做二次开发。当然在开发过程中也汲取了优良框架一些可取之处。 所用技术栈nodejs12 + eggjs2vue-climariadb 10 / mysql 8应用场景一般建站者:能够应用公布版进行网站疾速搭建上线,抉择您适合的皮肤切换格调,满足业务需要 开发者:能够疾速进行二次开发,上手容易,须要根本的前端常识就能够建站,改零碎遵循 MIT 协定齐全开源,所以代码能够收费商用。 开源协定 应用 MIT 开源许可协定,开源无限度可商用 链接地址 公众号【Github导航站】回复关键词【dora】获取git地址 截图演示后盾演示 前端演示 挪动端演示 结尾 本期就分享到这里,我是小编南风吹,专一分享好玩乏味、离奇、实用的开源我的项目及开发者工具、学习资源!心愿能与大家独特学习交换,欢送关注我的公众号【Github导航站】。

March 29, 2021 · 1 min · jiezi

关于node.js:Node之nrm安装使用

介绍npm包有很多的镜像源,有时须要切换npm的源,nrm包就是解决疾速切换问题的。nrm能够帮忙在不同的npm源地址之间轻松疾速地切换。 nrm内置了如下源: $ nrm ls* npm ----- https://registry.npmjs.org/ yarn ----- https://registry.yarnpkg.com cnpm ---- http://r.cnpmjs.org/ taobao -- https://registry.npm.taobao.org/ nj ------ https://registry.nodejitsu.com/ skimdb -- https://skimdb.npmjs.com/registry装置nrm关上终端运行npm install -g nrm命令 $ npm install -g nrm查看是否装置胜利: nrm --version $ nrm --version应用列出可抉择的源nrm ls$ nrm ls* npm ----- https://registry.npmjs.org/ yarn ----- https://registry.yarnpkg.com cnpm ---- http://r.cnpmjs.org/ taobao -- https://registry.npm.taobao.org/ nj ------ https://registry.nodejitsu.com/ skimdb -- https://skimdb.npmjs.com/registry后面带 * 号的示意正在应用的源 切换应用的源nrm use npm//switch registry to cnpm$ nrm use cnpm Registry has been set to: http://r.cnpmjs.org/增加一个源nrm add <registry> <url>如果想增加一个源,终端执行命令nrm add <registry> <url> [home],reigstry为源名,url为源的门路,home为源的主页(可不写) ...

March 25, 2021 · 1 min · jiezi

关于node.js:CabloyJS-460支持明细表

背景阐明为了更灵便、更便捷的反对理论业务场景的开发,作为NodeJS全栈框架,CabloyJS提供了草稿->正式->历史的数据生命周期治理、NodeJS工作流引擎,以及带来全新体验的mobile/pc自适应布局 CabloyJS 4.6.0又带来了明细表的治理,使咱们能够为任何业务数据增加明细表的性能 明细表的特点对于明细表的治理,并不仅仅是简略的CRUD操作,同时还具备以下特点: 一个主业务数据能够关联多个明细类型明细表 CRUD等指令的权限与主业务数据的权限协同与主业务数据一样反对草稿、正式、历史的生命周期反对在审批工作流中管制对明细表的CRUD权限反对惯例指令:上移、下移、克隆反对Mobile/PC自适应:默认状况下,在Mobile中显示列表,在PC中显示表格业务模块模版:module-business-details如果要开发一个带明细性能的业务模块,倡议应用业务模块模版module-business-details创立业务模块的文件骨架。此模版会主动创立与业务相干的代码,大量简化工作量 在新建业务模块之前,依然要先创立一个CabloyJS我的项目,具体参见:疾速开始$ cd /path/to/project$ npm init cabloy src/module/test-party --type=module-business-details如果网速慢,能够应用淘宝镜像:$ npm init cabloy src/module/test-party --type=module-business-details --registry=https://registry.npm.taobao.org目前,CabloyJS提供了三个模块文件模版: 名称阐明module-business此模版会创立与业务相干的代码,大量简化工作量module-business-details在module-business的根底上减少了与明细业务相干的代码文件module此模版仅蕴含根本的骨架代码文件更多文档对于明细表的更具体文档,请参见:明细 明细演示1. PC场景 2. Mobile场景 相干链接官网: https://cabloy.com/GitHub: https://github.com/zhennann/cabloy

March 24, 2021 · 1 min · jiezi

关于node.js:npm-install-报错-10054

首先,造成这个谬误很有可能是网络不稳固,连贯超时导致的, 如果再次尝试后仍然报错,能够执行上面的命令。 关上Git命令页面,执行git命令脚本:批改设置,解除ssl验证 git config --global http.sslVerify "false"此时,再执行git操作即可。 这种问题经常出现在npm install时,谬误提醒如下:...npm WARN deprecated left-pad@1.3.0: use String.prototype.padStart() npm ERR! Error while executing:npm ERR! C:\Program Files\Git\mingw64\bin\git.EXE ls-remote -h -t https://github.com/nhn/raphael.git npm ERR!npm ERR! fatal: unable to access 'https://github.com/nhn/raphael.git/': OpenSSL SSL_read: Connection was _read: Connection was reset, errno 10054npm ERR!npm ERR! exited with error code: 128...

March 24, 2021 · 1 min · jiezi

关于ecmascript:ES6中的新特性Iterables和iterators

简介为了不便汇合数据的遍历,在ES6中引入了一个iteration的概念。为咱们提供了更加不便的数据遍历的伎俩。 一起来学习一下吧。 什么是iterationiteration也称为遍历,就是像数据库的游标一样,一步一步的遍历汇合或者对象的数据。 依据ES6的定义,iteration次要由三局部组成: Iterable先看下Iterable的定义: interface Iterable { [Symbol.iterator]() : Iterator;}Iterable示意这个对象外面有可遍历的数据,并且须要实现一个能够生成Iterator的工厂办法。 Iteratorinterface Iterator { next() : IteratorResult;}能够从Iterable中构建Iterator。Iterator是一个相似游标的概念,能够通过next拜访到IteratorResult。 IteratorResultIteratorResult是每次调用next办法失去的数据。 interface IteratorResult { value: any; done: boolean;}IteratorResult中除了有一个value值示意要获取到的数据之外,还有一个done,示意是否遍历实现。 Iterable是一个接口,通过这个接口,咱们能够连贯数据提供者和数据消费者。 Iterable对象叫做数据提供者。对于数据消费者来说,除了能够调用next办法来获取数据之外,还能够应用for-of 或者 ...扩大运算符来进行遍历。 for-of的例子: for (const x of ['a', 'b', 'c']) { console.log(x); }...扩大运算符的例子: const arr = [...new Set(['a', 'b', 'c'])];Iterable对象ES6中,能够被称为Iterable对象的有上面几种: ArraysStringsMapsSetsDOM先看一个Arrays的状况,如果咱们有一个Arrays,能够通过Symbol.iterator这个key来获取到Iterator: > const arr = ['a', 'b', 'c'];> const iter = arr[Symbol.iterator]();> iter.next(){ value: 'a', done: false }> iter.next(){ value: 'b', done: false }> iter.next(){ value: 'c', done: false }> iter.next(){ value: undefined, done: true }更加简略的方法就是应用for-of: ...

March 21, 2021 · 3 min · jiezi

关于node.js:11111

Don't Repeat Yourself中间件在软件畛域是一个十分广的概念。除操作系统的软件都能够称为中间件。比方:消息中间件、ESB中间件、日志中间件、数据库中间件等。 connect被定义位Node平台的中间件框架,从定位上看Connect肯定是出众的,宽泛兼容的,稳固的,根底的平台性框架。如果攻克Connect,会有助于咱们更理解Node的世界。Express就是给予Connect开发的。 connect的模型很是简略,通过use注册中间件,每一个中间件接管request和response,若是发现request是该中间件解决的,那么解决完后通过response.end输入,不然通过next交给下一个中间件解决。 https://www.shangmayuan.com/a...

March 17, 2021 · 1 min · jiezi

关于webpack:savedev与save的区别-npm

npm install 在装置 npm 包时,有两种命令参数能够把它们的信息写入 package.json 文件-save || -S // 运行依赖(公布)–save-dev || -D // 开发依赖(辅助){ "dependencies": { // -save || -S // 运行依赖(公布) "vue": "^3.0.1" }, "devDependencies": { // –save-dev || -D // 开发依赖(辅助) "webpack": "^5.1.0", }}

March 16, 2021 · 1 min · jiezi

关于node.js:Windows10Nodejs12将pm2安装为Windows服务

参考将Node.js应用程序作为Windows服务运行pm2-windows-service官网的issues概述遇到个需要,要在Windows10里把pm2作为服务主动启动,很天然的找到了pm2-windows-service这个npm库以及相干的中文文章,而后照方抓药,然而竟然卡住了…… 又是一番查找,托谷哥的福,找到了解决方案,这里简略记一下。 步骤全局装置pm2, pm2-windows-service及其依赖cnpm i bufferutil@^4.0.1 utf-8-validate@^5.0.2 pm2 pm2-windows-service -g降级inquirer模块 cd C:\Users\<用户>\AppData\Roaming\npm\node_modules\pm2-windows-servicencu inquirer -ucnpm install而后即可进行失常操作,进行服务装置 pm2-service-install而后命令行输出services.msc启动服务管理器,即可看到PM2服务已启动删除服务,能够用pm2-service-uninstall在pm2增加工作后,不要忘了用pm2 save保留当前任务列表,下次重启服务器,pm2服务启动后可主动主动这些工作

March 15, 2021 · 1 min · jiezi

关于node.js:对于express框架的基本理解

引言*因为nodejs是之前很久学的,当初曾经遗记了语法规定,当初间接从框架下手,反其道而行之去了解nodejs。在nodejs外面创立web服务器是很麻烦的事件,要用到http模块,express框架就是来优化这么一个过程的工具。在学习express框架的时候发现了它于vue的殊途同归之妙,在路由上的用法及其类似。可能这也是为什么vue和express都叫做框架的起因吧,不过express是服务端的框架。* 装置在终端应用 `cnpm/npm install express`即可应用 //须要绑定到一个对象身上能力去应用它,所以 const express = require('express'); //绑定之后须要用这个对象去创立一个web服务器 const app = express(); //增加路由,get只能增加特定路由,如果为'/'则404,但use都能够用,祥见下一篇文章 app.get('/home', (req, res) => { res.send("第一个页面") }) //在创立实现之后须要映射到一个端口下来发挥作用 app.listen(3000) //表明一下程序曾经运行了 console.log('运行完结');根底性能如果只用根本的创立服务器那真的太节约express了,它还包含很多简单的性能中间件 //在回调函数外面退出next,在最初一行指定指标 app.get('/home', (req, res, next) => { console.log('跳转到下一路由'); next(); }) //下一路由地址放弃雷同 app.get('/home',(req,res)=>{ res.send('跳转路由实现') }) //或者应用use来承受所有信息,路由为空示意接管全副 app.use((req,res)=>{ res.send('跳转路由实现') })中间件之拦挡 //如果网站正在保护,则能够拦挡所有申请 app.use((req,res)=>{ res.send('网站正在保护') }) //如果是产生谬误则进行拦挡 app.get('/index', (req, res) => { throw new Error('程序产生谬误'); }) //用use接管所有错误信息,这里必须要填next app.use((err, req, res, next) => { //因为用的框架,所以状态码就算遇到谬误也会是200,这里设置成500 res.status(500).send(err.message); })拦挡异步谬误//引入异步模块 const promisify = require('util').promisify //引入读写模块 const fs = require('fs') //让读写模块异步 const readFile = promisify(fs.readFile)app.get('/index', async(req, res,next) => { try { //轻易设置门路让程序抛出谬误 await readFile('不存在.txt') } catch (err) { next(err) } }) app.use((err, req, res, next) => { res.send(err) })路由模块化 在express中能够通过内置构造函数router生成二级路由 //创立路由对象 const home=express.Router(); //用use指向子路由 app.use('/home',home) //子路由地址为/index home.get('/index',(req,res)=>{ res.send('子路由模块') }) 在理论开发过程中个别会把两个路由写在不同的文件外面 在主路由外面引入并进行门路匹配index.js:const home=require('./home.js') app.use('/home',home)home.js:const express = require('express'); const home = express.Router(); home.get('/index', (req, res) => { res.send("欢送来到主页") }); module.exports = home

March 12, 2021 · 1 min · jiezi

关于node.js:VuePress在build打包时window-document-is-not-defined

前言近期在造一个 vue 的组件库(这也有不少故事能够讲...),造完轮子后须要编写组件文档,选了 vuepress,在文档中须要代码演示,天然就须要引入组件库,引入组件库后编写文档失常应用没有问题,然而在 build 的时候就出麻烦了... 问题问题一 ReferenceError: document is not defined 呈现这个问题的起因是我在编写 vue 组件的时候,在.vue文件中引入了款式文件,就是上面这个样子: <style lang="less"> @import '../style/content.less'; </style>这个大家应该很相熟了,失常的引入款式,然而问题是组件库代码编译过后,会用到 document.querySelectory() 来进行款式解决,而 vuepress 所有的页面在生成动态 HTML 时都须要通过 Node.js 服务端渲染, Node.js 环境中天然没有 document 对象,这时候拜访浏览器/DOM 中的 API 天然会报错。 本地开发没有问题,然而 build 就会出错问题二window is not defined 呈现这个问题同样是因为在编写组件时用到了 window 对象,而 Node.js 中没有 window 对象。 解决第一回合 vuepress 官网给出解决办法,就是利用 vue 的动静组件, <template> <component v-if="dynamicComponent" :is="dynamicComponent"></component></template><script> export default { data() { return { dynamicComponent: null } }, mounted () { import('./lib-that-access-window-on-import').then(module => { this.dynamicComponent = module.default }) }} </script>具体查看浏览器的 API 拜访限度这种形式诚然能解决问题,然而很麻烦,想想我要编写十几个组件文档,写 demo 的时候每次都要这样解决,要是遇到简单的示例,一个 demo 外面用到了好几个组件,那岂不是麻烦得很,不够优雅,不够优雅。 ...

March 8, 2021 · 1 min · jiezi

关于node.js:Wechaty初探

本文为python-wechaty + wechaty-puppet-padlocal的初探 注意事项wechaty-puppet-padlocal目前只能用国内的公网IP新注册的wechat小号会无奈登入Test Date:March 1, 2021环境:本地的手机(iPad or 手机都能够)PC(本文用Mac)阿里云上的虚拟机 for puppet架构 在虚拟机上运行wechaty-puppet验证API有无注册胜利运行本地python-wechaty-getting-started扫码登入Step 1 [wechaty-puppet-padlocal]你会须要一个国内的公网IP+Token(请向管理员注册)来让wechaty-puppet失效虚拟机局部,试用or收费计划你能够选用阿里云or华为云的or GCP  很惋惜google没有在国内的IP,不然你还能够顺便玩一下gcp的k8s倡议你还是应用国内资源 注册个ubuntu20.04即可,注意安全组要放行port 8788在ubuntu cmdline里运行已下指令apt updateapt install docker.iodocker pull wechaty/wechatyexport WECHATY_PUPPET_PADLOCAL_TOKEN=puppet_padlocal_xxxxxxxxxxxxxxxxxxexport WECHATY_PUPPET_SERVER_PORT=8788export WECHATY_PUPPET=wechaty-puppet-padlocalexport WECHATY_LOG=verbosedocker run --rm -ti -e WECHATY_LOG -e WECHATY_PUPPET -e WECHATY_HOSTIE_PORT -e WECHATY_TOKEN -p "$WECHATY_HOSTIE_PORT" wechaty/wechaty3.能够下指令检查一下是否失常运行,如图 netstat -ntlpdocker container ls4.你能够telnet 虚拟机IP:8788 繁难debug一下通不通5.(Optional)你能够運行將docker run改為docker-compose,虛擬機當機後能够自動長起來 Step 2 [验证hostie token]拜访https://api.chatie.io/v0/host...去测验你的token是否胜利注册,如果不行请回到step1去查看。Good:{"ip":"47.119.129.29","port":8788}No Good:{"ip":"0.0.0.0","port":0} Step 3 [本地运行python]python-wechaty-getting-started你须要Python3.7+运行以下cmd git clone https://github.com/wechaty/python-wechaty-getting-startedcd python-wechaty-getting-startedpip3 install -r requirements.txtexport WECHATY_PUPPET=wechaty-puppet-serviceexport WECHATY_PUPPET_SERVICE_TOKEN=your_token_at_herepython3 examples/ding-dong-bot.py坐等QR code呈现扫码就好 Step 4 [微信扫码]目前用新注册帐号会失败扫完后就登入了 ...

March 8, 2021 · 1 min · jiezi

关于node.js:getFileStream-获取不到自定义字段

Eggjs 应用ctx.getFileStream进行文件上传最近在应用eggjs上传文件时,无奈获取到前端定义的字段,始终为空,在此记录一下前端代码 handleRequest(param) { let fileObj = param.file; // FormData 对象 let form = new FormData(); // 文件对象 form.append('bizId', this.apartment.id); form.append('bizType', '1'); form.append('file', fileObj); // 留神这个中央挪动要放append到最初面 fileApi.uploadSave(form).then((res) => { //... }) },后端 // 应用了案例云的OSS async ossStreamSave() { const { ctx } = this; try { // ★★★★★ 提醒,前端 formData.append(‘filename’, file) 必须放到最初,否则ctx.getFileStream()取流实现时stream.fields依然是空的 let stream; stream = await ctx.getFileStream(); const params = { bizId: stream.fields.bizId, bizType: stream.fields.bizType, url: '', submittedFileName: stream.filename, contextType: stream.mimeType, ext: stream.filename.split('.')[1], }; const uid = UUID.v4(); const name = 'tks/' + path.basename(`${uid}.${params.ext}`); const result = await client.put(name, stream); params.url = result.url; const res = await ctx.model.TksFile.create(params); return res; } catch (err) { return false; } }参考:https://blog.csdn.net/qq_3615... ...

March 5, 2021 · 1 min · jiezi

关于node.js:平台建设的7大问题蚂蚁AI平台实践深度总结

简介: 在反对蚂蚁简直所有外围业务运行和倒退的过程中,咱们在平台建设、业务反对、平台经营、AI翻新以及AI整体经营等各个方面做了很多尝试,有了不少的播种和感悟,在此分享给大家。 过来几年,我和团队始终在负责蚂蚁团体外部相干平台产品的设计和经营工作。 这些平台产品包含人工智能部的A/B测试平台、机器学习平台、金融常识图谱平台、NLP平台、智能文案平台、金融视觉(CV)平台、搜寻平台、机器人平台、标注平台等,以及风控团队的相干平台产品。这些平台产品,在背地反对了蚂蚁简直所有外围业务的运行和倒退。 整个过程当中,咱们在平台建设、业务反对、平台经营、AI翻新以及AI整体经营等各个方面做了很多尝试,有了不少的播种和感悟。 最近,我花了一些工夫,将其初步梳理进去,写成了这篇文章。 文章的内容涵盖了“需要治理、平台设计、产品验证、平台协同、兽性反抗、跨界思维、挑战/成长”等7个方面,既有一些形象的、办法层面的总结,也有很多实在的、有体感的案例。 篇幅比拟长,约1.5万字。感兴趣的话,能够珍藏下前面缓缓看。 心愿本文对你有所启发,更期待能抛砖引玉,跟大家做深刻的探讨和交换。 一 、需要治理:“角色错位”与“无我境界”1 、开掘需要,警觉“角色错位”,杜绝“闭门造车”。 做好产品的第一步,就是把握好需要,必须搞清楚每一个产品和性能的真正用户是谁。 对于C端产品,这个问题比拟好解决,因为设计者和使用者往往是重合的。但对于技术平台类产品、B端产品,这两者常常是错位的,即设计者可能并不是真正的用户。 举个例子,支付宝的产品经理在日常生活当中天天用支付宝付款、理财,他就是个典型的支付宝用户,所以设计者与使用者就是同一个人。而在技术平台、B端产品当中,产品的设计者能够用本人的产品,但基本上仅限于做测试、做验证,真正的用户却是其余的人。 因而,设计者对于产品需要的一些推理判断,可能会与真实情况有差异,即便他用了,那个以测试为目标的应用和实在的应用,还是有区别的。 由此可见,正是因为技术平台类产品中这种角色的错位,就容易导致需要把控出问题。 上面,先从咱们标注平台的一个小故事开始讲起。 去年12月的一天,咱们标注平台的相干同学散会,进行产品设计评审。 其间,针对一个标注页面的产品设计细节问题,在坐的产品经理、UED、前端、后端各个岗位的同学畅所欲言、争执得不可开交。 忽然间,我意识到一个重大的问题——那就是会议室的所有同学,并不是这个feature的用户。 因为具体的标注工作,都是外包公司的数百个标注人员做的,他们才是标注页面的真正用户。 不是真正的用户、没有处在那个场景,就很难理解实在的状况。于是,大家就只能依据本人的教训和业余能力,进行判断和推演。 做产品不能闭门造车。于是,咱们就随即安顿相干同学去了标注外包公司做现场调研。 一开始,咱们与几个标注团队的小组长进行小范畴的初步沟通。过后,随口问了下产品应用状况,他们统一反馈“没什么问题,挺好用的”。 这样的答复很失常,毕竟这么简略、间接的问法,是很难获取到有价值的信息、理解到用户的需要。 在产品经理的行业,咱们常常说的一句话是,在汽车被创造之前,如果你间接问用户要什么,他只能说“我要一匹更快的马”。钉钉原负责人无招同学来蚂蚁做“钉钉守业之路”的分享时,也谈到这个问题。他的观点是,见到用户不能只是“就事论事”,只问产品应用相干的浅层次的问题。(即便问这样的问题,也不能问“你有什么需要”之类很难取得实在需要的直白的问题)。正确的形式是,先把具体的产品抛下,多理解客户的背景、业务、状态等整体的、背景的、前因后果的信息,要体现出对客户“感兴趣”,要想成为客户的敌人。只有这样,客户才违心跟你多聊、深聊,只有这样,你能力捕捉到有价值的信息。再加上,察看客户的具体行为和操作,就能捕捉到实在的需要,能力做到有所洞察。于是,完结会议后,咱们要求上楼到标注员工的办公区,具体看看状况。 当咱们站在标注人员身后,仔细观察他们的操作、与他们深刻交谈后,就有了新的发现。 很多原来没有设想到的应用办法和场景、产品设计的细节问题,在标注人员的一直操作中,就显现出来了。之前产品评审会上大家争执的问题,天然就有了答案。 半天下来,咱们总共记录下数十个有价值的反馈和发现,并在后续工作中,一一做了解决和跟进。 可见,如果你不是真正的用户,你没有亲眼察看真正用户的操作,很多问题你是无奈预料到的。 大家IQ都不差,遇到问题,咱们往往习惯于谈办法、讲逻辑,常常在会议室外面唇枪舌战甚至拍桌子瞪眼睛,最初谁也压服不了谁,得不到无效的论断。 在这时,无妨先问下本人“真正的用户是谁?”,再试试“笨办法”,走出办公室,走到客户那里,去问问他们、跟他们聊聊天,看看他们怎么用咱们的产品。 那时候,很多问题便恍然大悟了。 2 、满足需要,一直“由浅入深”,修炼“无我境界”。 接着,让咱们的思考再深刻一些。 当初,假如你曾经明确了用户是谁、摸到了需要的大略脉络,那也要考量“对需要了解是否深刻”的问题,即浅层需要和深层需要的问题。 换句话,也是伎俩和目标的问题——“浅层需要”往往只是伎俩,而“深层需要”才是目标。 举个例子,对于咱们负责的金融视觉平台,有用户反馈“我须要模型报告”,即模型训练进去后,将一些“准确率、召回率、AUC之类”的指标,用图表的形式展现进去。 如果你只是将这个需要做了,那是不够的。 为什么呢?因为用户要的模型报告,只是“浅层需要”——他确实须要看各种指标,但他最想要的是,在新模型训练进去后,他要对不同版本的模型成果进行比照——不仅要晓得指标是多少,更想晓得指标的具体变动,哪些升了、哪些降了以及具体数值是多少。 只有这样,才算是满足了深层需要。 情理是相通的,相似问题在C端产品中也会碰到。 如果你注意的话,你会发现很多电商网站、汽车导购产品的产品经理曾经摸到了深层需要。 比方,汽车网站外面根本都有一个“车型比照”性能:不仅能将不同车型的各项配置、参数,用表格逐项列出来,而且还提供了“高亮不同配置、暗藏雷同配置”等贴心性能。这就是深层次地满足了用户的需要。 因而,对于一个需要,多问几个为什么,多问本人“这是用户的实在目标吗?他用这个性能到底想干什么”等。只有这样,才有可能涉及到用户深层次的需要,才有可能做出让用户感到很贴心的性能。 对于深刻满足用户需要,除了做浅层、深层的剖析之外,还能够采纳“分而治之”的思路,将产品从模块和性能上分层,即分出“N级火箭”,每一级“火箭”用来满足不同类型的用户需要,或者同一用户在不同阶段的需要。 举个例子,只管咱们的图谱、NLP、CV、搜寻、机器人、标注等几个平台产品的性能各不相同,但咱们还是找到了共性,即形象出了需要分级和业务赋能的“五级火箭”,包含“性能嵌入、API调用、数据训练、模型定制、算法开发”等五级。业务方能够依据具体情况,来抉择不同的接入形式。 第一级,性能嵌入:通过iframe等实现老本最低的伎俩,将平台的某个功能模块嵌入到本人的零碎当中。第二级,API调用:间接调用平台提供的成熟API,比方调用身份证、驾驶证之类的OCR辨认的API。第三级,数据训练:平台的模型合乎需要,但须要提供本人的训练数据或者字典数据等,来解决具体场景需要。第四级,模型定制:平台的现场模型不太符合要求,所以要对算法参数进行配置,而后训练出合乎本人需要的新模型。第五级,算法开发:最高级的状况,就是业务方懂算法、要开发新算法。平台则提供“算法开发、数据管理、模型训练、模型测试和公布”等一系列深层次的能力,来晋升算法研发的效率。上述“五级火箭”,由浅入深地满足了不同类型用户,以及同一个用户不同阶段的需要。 记得多年前,我加入了一个治理方面的高级培训班。培训有好几天,内容很多,不过简直所有的培训内容我都遗记了——除了一位老师无心中介绍的一个“万能四步法”。所谓四步法,就是“分类-排序-找法则-利用”这四个步骤。无论在学习新的畛域常识、接手新的工作,还是来到新的环境时,都能够尝试这个万能四步法,置信再简单的问题都能迎刃而解。用户分层、五级火箭,就是“分类-排序”的一个利用。谈完“需要/用户分层、五级火箭”了,那是否就是对用户需要360度、无死角地满足了呢? 答案是否定的,因为咱们还没有做到“无我境界” 。 所谓“无我”的境界,就是满足用户需要的时候,不能只思考“我是谁、我有什么”,而要忘掉本人,去看用户须要什么,什么货色对用户最有用。 比方,尽管你是做AI技术平台产品经理,但你眼里不能只有AI、算法、模型——要做到“无我”,就是要做到:如果有一种非算法、非AI的产品策略,若能切实帮到业务,那也应该去做。 在业务同学的眼里,有没有算法没关系,是不是高科技不重要——而有没有业务成果才要害。正所谓,不论白猫黑猫,抓到老鼠才是好猫。 比方,咱们的智能文案平台,可能智能生成千人千面的营销文案。过来,始终在迭代产品、晋升算法能力,力求生成更加智能、精准和个性化的文案。 然而,大家晓得,算法的晋升不可能欲速不达,算法成果都是缓缓地打磨和优化的。 在这个过程中,产品经理同学不能干等。 于是,咱们就在思考,不论如许浅近的算法、如许智能的平台,咱们生产的依然是文案。而文案这个岗位,随着广告行业的倒退曾经存在了数百年,那么,肯定有成熟的方法论和模式。 作为互联网从业者,咱们崇尚翻新和颠覆,但咱们还必须对行业保留敬畏之心。 于是,咱们的产品经理同学就去把一些市场营销、广告文案经典书籍研读了一番,总结出了所谓“18种优质文案句式/模板”,这外面既有文案从业者的经验总结,也有广告学、心理学等畛域的迷信原理。 将这些“优质句式”、“文案法令”产品化之后,配合算法和技术,就能给业务输入更有成果的文案。 咱们置信,机器不能齐全代替人,机器智能和行业常识、专家教训等人类智慧,肯定会井水不犯河水、交相辉映。 二 、平台设计:平台产品,也必须“秒懂”讲完需要,再来说说设计。 在互联网行业,面向C端用户的产品不仅供应富余、极大丰富,而且广泛都收费,获取老本根本为0。 没有付出,就不会“珍惜”。 所以,对用户来说,产品必须容易上手,即必须“秒懂”。如果用户几分钟甚至几十秒看不懂、不会用,那他根本就放弃了,产品就没有机会了。 对于中台、平台产品来说,其实也是这样的,只不过用户遇到不爽的体验只能忍忍,因为应用你的产品来解决他的业务需要,这是他的实质工作。 ...

March 4, 2021 · 2 min · jiezi

关于node.js:快手基于-Flink-的持续优化与实践

简介: 快手基于 Flink 的继续优化与实际的介绍。一、Flink 稳定性继续优化第一局部是 Flink 稳定性的继续优化。该局部包含两个方面,第一个方面,次要介绍快手在 Flink Kafka Connector 方面做的一些高可用,是基于外部的双机房读或双机房写和一些容错的策略。第二局部对于 Flink 工作的故障复原。咱们在减速故障复原方面做了一些优化工作。 首先,介绍 Source 方面的高可用。在公司外部比拟重要的数据写 Kafka 时,Kafka 层面为保障高可用个别都会创立双集群的 topic。双集群的 topic 独特承当全副流量,如果单集群产生故障,上游主动分流。Kafka 层面通过这种形式做到双集群的高可用。然而 Flink 工作在生产双集群 topic 时,自身是不能做到高可用的。Flink 工作通过两个 Source union 形式生产,Source 别离感知上游 topic 故障,单集群故障需手动将故障 Source 摘除。这种形式的毛病是故障时须要人工的干涉,必须手动去批改代码的逻辑,程序外部自身是不能做到高可用的。这是做双机房读的背景。 为了解决上述问题,咱们封装了一个 Kafka 的 Cluster Source,它在 API 上反对读取双集群的 topic。同时做到,能够容忍单集群故障,集群故障复原时也能够主动将故障集群重新加入。 接下来是对于 Sink 方面的高可用。Flink 写双集群 Kafka topic,会定义不同集群 Sink,逻辑内管制拆流。这种形式灵活性差,且不能容忍单机房故障。如果单集群产生故障,仍须要手动摘除对应的 Sink。 同样,针对 sink 咱们也定制了一个 Cluster Sink,它 API 上反对写双集群 topic。具体写的策略,能够反对轮询和主从写的形式。如果单集群产生故障,逻辑内会主动将流量切到失常集群 topic。如果单集群故障复原之后,也能感知到集群的复原,能够主动的再把相应集群复原回来。 另外,基于 Kafka 的 connector,咱们也做了一些容错的策略,这里提到三点。 ...

March 4, 2021 · 2 min · jiezi

关于node.js:Nodejs安装及环境配置

1、下载安装点击这里下载 依据本人电脑系统及位数抉择,我这里抉择windows64位.msi格局安装包 .msi和.zip格局区别: .msi是Windows installer开发进去的程序安装文件,它能够让你装置,批改,卸载你所装置的程序。说白了.msi就是Windows installer的数据包,把所有和安装文件相干的内容封装在一个包里。.zip是一个压缩包,解压之后即可,不须要装置 下载实现后,双击安装包,开始装置,始终点next即可,装置门路默认在C:Program Files下,也能够自定义批改 npm package manager示意npm包管理器 online documentation shortcuts 在线文档快捷方式 Add to PATH增加node装置门路到环境变量 装置实现如图所示,这里我批改了node的装置门路C:node 在这里插入图片形容 装置实现后,.msi格局的安装包曾经将node.exe增加到零碎环境变量path中,如果你下载的是.zip格局,因为没有装置过程,所以须要手动将node.exe所在目录增加到环境变量path中,查看零碎变量验证 image.png 既然曾经将node增加到全局零碎变量,咱们能够间接在CMD窗口中任意地位执行node,关上CMD窗口,执行命令node -v查看node版本 v14.7.0 最新版的node在装置时同时也装置了npm,执行npm -v查看npm版本 6.14.7 2、批改全局依赖包下载门路默认状况下,咱们在执行npm install -g XXXX下载全局包时,这个包的默认寄存门路位C:Users用户名AppDataRoamingnpmnode_modules下,能够通过CMD指令npm root -g查看 C:UsersliaijieAppDataRoamingnpmnode_modules 然而有时候咱们不想让全局包放在这里,咱们能够自定义寄存目录,在CMD窗口执行以下两条命令批改默认门路: npm config set prefix "C:nodenode_global" npm config set cache "C:nodenode_cache" 或者关上c:nodenode_modulesnpm.npmrc文件,批改如下: prefix =C:nodenode_globalcache = C:nodenode_cache 以上操作示意,批改全局包下载目录为C:nodenode_global,缓存目录为C:nodenode_cache,并会主动创立node_global目录,而node_cache目录是缓存目录,会在你下载全局包时主动创立 3、配置环境变量因为咱们批改了全局包的下载门路,那么自然而然,咱们下载的全局包就会寄存在c:nodenode_globalnode_modules,而其对应的cmd指令会寄存在c:nodenode_global 我全局装置一个vue-cli脚手架 npm install @vue/cli -g 装置实现后: 我应用CMD命令vue create myproject指令创立一个我的项目,显示如下 ...

March 4, 2021 · 1 min · jiezi

关于node.js:用代码实践Web缓存

Web缓存是能够主动保留常见文档正本的HTTP设施。当Web申请到达缓存时,如果本地有“已缓存的正本”,就能够从本地存储设备而不是原始服务器中提取这个文档。下面是《HTTP权威指南》中对Web缓存的定义,缓存的益处次要有以下几点: 缩小了冗余数据的传输;缩小了客户端的网络申请,也升高了原始服务器的压力;升高了时延,页面加载更快。总结一下就是省流量,省带宽,还贼快。那么缓存是如何工作的呢?客户端和服务端是如何协调缓存的时效性的呢?上面咱们用代码来一步一步揭晓缓存的工作原理。 一、浏览器缓存当咱们在浏览器地址栏敲入localhost:8080/test.txt并回车时,咱们是向指定的服务端发动对text.txt文件的申请, 服务端在接管到这个申请之后,找到了这个文件并筹备返回给客户端,并通过设置Cache-Control和Expires两个response header通知客户端这个文件要缓存下来,在过期之前别跟我要了。 首先咱们看一下我的项目目录: |-- Cache |-- index.js |-- assets |-- index.html |-- test.txt具体实现代码如下: <!-- index.html -->...<a href="./test.txt">test.txt</a>...// index.jsconst http = require('http');const path = require('path');const fs = require('fs');http.createServer((req, res) => { const requestUrl = path.join(__dirname, '/assets', path.normalize(req.url)); fs.stat(requestUrl, (err, stats) => { if (err || !stats.isFile) { res.writeHead(404, 'Not Found'); res.end(); } else { const readStream = fs.createReadStream(requestUrl); const maxAge = 10; const expireDate = new Date( new Date().getTime() + maxAge * 1000 ).toUTCString(); res.setHeader('Cache-Control', `max-age=${maxAge}, public`); res.setHeader('Expires', expireDate); readStream.pipe(res); } });}).listen(8080);那Cache-Control和Expires这个两个response header又代表什么意思呢?Cache-Control:max-age=500示意设置缓存存储的最大周期为500秒,超过这个工夫缓存被认为过期。Expires:Tue, 23 Feb 2021 01:23:48 GMT示意在Tue, 23 Feb 2021 01:23:48 GMT这个日期之后文档过期。 ...

February 27, 2021 · 2 min · jiezi

关于node.js:Webpack-的使用

webpack 用于编译 JavaScript 模块。 根本装置mkdir webpack-democd webpack-demonpm init -ynpm install webpack webpack-cli --save-dev编写我的项目 webpack-demo |- package.json+ |- index.html+ |- /src+ |- index.jsindex.html <!DOCTYPE html><html> <head> <meta charset="utf-8" /> <title>起步</title> <script src="https://unpkg.com/lodash@4.17.20"></script> </head> <body> <script src="./src/index.js"></script> </body></html>src/index.js function component() { const element = document.createElement('div'); element.innerHTML = _.join(['Hello', 'webpack'], ' '); return element;}document.body.appendChild(component());调整 package.json 文件,避免意外公布代码。 package.json { "name": "webpack-demo", "version": "1.0.0", "description": "",- "main": "index.js",+ "private": true, "scripts": { "test": "echo \"Error: no test specified\" && exit 1" }, "keywords": [], "author": "", "license": "ISC", "devDependencies": { "webpack": "^5.4.0", "webpack-cli": "^4.2.0" } }应用 webpack 来治理JS脚本 webpack-demo |- package.json+ |- webpack.config.js+ |- /dist+ |- index.html- |- index.html |- /src |- index.jsnpm install --save lodashsrc/index.js ...

February 26, 2021 · 2 min · jiezi

关于node.js:NPM-install-的使用

运行时依赖(默认)下载安装包到我的项目的node_modules目录中,并将依赖增加进 package.json 文件的 dependencies 属性。 npm install <packname>npm install <packname> --save-prodnpm install <packname> -P开发时依赖下载安装包到我的项目的node_modules目录中,并将依赖增加进 package.json 文件的 devDependencies 属性。 npm install <packname> --save-devnpm install <packname> -D仅下载依赖仅下载安装包到我的项目的node_modules目录中,不批改 package.json 文件。 npm install <packname> --no-save装置依赖# 装置 package.json 中的所有依赖npm install# 仅装置 dependencies 依赖npm install --production# Windows 设置环境变量并执行命令set NODE_ENV=production && xxxx# Linux 设置环境变量并执行命令NODE_ENV=production xxxx参考:https://docs.npmjs.com/cli/v7...

February 25, 2021 · 1 min · jiezi

关于node.js:day34-gulp

day34 gulp1. Gulp简介gulp是前端开发过程中对代码进行构建的工具,是自动化我的项目的构建利器;她不仅能对网站资源进行优化,而且在开发过程中很多反复的工作可能应用正确的工具主动实现;应用她,咱们不仅能够很欢快的编写代码,而且大大提高咱们的工作效率。gulp是基于Nodejs的主动工作运行器,她能自动化地实现 javascript/coffee/sass/less/html/image/css 等文件的的测试、查看、合并、压缩、格式化、浏览器主动刷新、部署文件生成,并监听文件在改变后反复指定的这些步骤。在实现上,她借鉴了Unix操作系统的管道(pipe)思维,前一级的输入,间接变成后一级的输出,使得在操作上非常简单。gulp 和grunt 十分相似,但相比于 grunt 的频繁 IO 操作,gulp 的流操作,能更快地更便捷地实现构建工作。2. Gulp环境搭建1)装置nodeJs阐明:gulp是基于nodejs,天经地义须要装置nodejs装置:关上nodejs官网(https://nodejs.org/en/),点击硕大的绿色Download按钮,它会依据零碎信息抉择对应版本(.msi文件)测试:按window + r 输出cmd回车,而后输出npm -v确保曾经配置到了环境变量, 这样你就能够在全局范畴内去应用它了如果想理解环境变量:进入以下地址:https://blog.csdn.net/jiang77...npm的解释: npm是Node.js的包管理工具(package manager)在Node.js上开发时,会用到很多他人写的JavaScript代码。如果须要应用他人写的某个包,每次都依据名称搜寻一下官方网站,下载代码,解压,再应用,十分繁琐。于是一个集中管理的工具应运而生:大家都把本人开发的模块打包后放到npm官网上,如果要应用,间接通过npm装置就能够间接用,不必管代码存在哪,应该从哪下载。更重要的是,如果咱们要应用模块A,而模块A又依赖于模块B,模块B又依赖于模块X和模块Y,npm能够依据依赖关系,把所有依赖的包都下载下来并治理起来。否则,靠咱们本人手动治理,必定既麻烦又容易出错。2)装置 cnpm因为npm装置插件是从国外服务器下载,受网络影响大,可能出现异常;如果npm的服务器在中国就好了,所以咱们乐于分享的淘宝团队干了这事。网址:http://npm.taobao.org装置: cmd(命令行) 执行: npm install cnpm -g --registry=https://registry.npm.taobao.orgcnpm -v 测试是否装置胜利留神:cnpm跟npm用法完全一致,只是在执行命令时将npm改为cnpm(以下操作将以cnpm代替npm)3) 全局装置gulpcmd命令: cnpm install gulp -ggulp -v, 呈现版本号即为正确装置全局装置gulp的目标是:能够应用gulp命令(就跟应用npm的命令一样)4) gulp在我的项目中如何应用 (新我的项目的步骤)1. 新建package.json配置文件(初始化一个我的项目)cmd命令: cnpm init一路回车,就会在我的项目的文件夹下产生一个package.json文件 2. 本地装置gulp(在我的项目目录下装置gulp)此步骤的目标是:把gulp里的所有的js文件从服务器上下载到我的项目目录下; 在本目录下cmd(命令行)执行: cnpm install gulp --save-dev装置实现后,就会在我的项目目录下产生一个node_modules文件 3. 应用gulp在我的项目根目录下创立 gulpfile.js 在这个js文件中写上js代码,就能够应用。gulp.task("工作名称",回调函数);gulp.src("源文件门路"); gulp.src() 是读取将要解决的文件,即源文件gulp.dest("目标门路"); gulp.dest() 是解决后的文件的门路,即目标文件pipe(操作); pipe() 管道,是如何解决该文件(如:sass编译,复制文件,压缩文件等)原生的gulp有:task src dest watch 原生gulp (4个)复制文件const gulp = require("gulp");// gulp原生办法// gulp.task("工作名称",回调函数)gulp.task("_copy",function(){ gulp.src("2fs.txt").pipe(gulp.dest("d:/dest"));});// cmd命令行: gulp 工作名, 如gulp _copy后果:d:/dest下有了2fs.txt文件,阐明复制胜利了。 ...

February 25, 2021 · 1 min · jiezi

关于node.js:NPM-Scripts-的使用

npm 脚本概念npm 容许在 package.json 文件中应用 scripts 字段定义脚本: { // ... "scripts": { "build": "node build.js" }}执行脚本: $ npm run build查看所有可用脚本: $ npm run脚本执行原理每当执行 npm run,命令会主动新建一个 Shell,在这个 Shell 外面执行指定的脚本命令。因而,只有是 Shell 能够运行的命令,就能够写在 npm 脚本外面。 npm run 会将当前目录的 node_modules/.bin 子目录退出 PATH 变量中,执行完结后,再将 PATH 变量复原原样。 所以,node_modules/.bin 子目录外面的所有脚本,都能够间接用脚本名调用,而不用加上门路。 npm 脚本的惟一要求是能够在 Shell 中执行,因而它不肯定是 Node 脚本,任何可执行文件都能够写在外面。 脚本通配符"lint": "jshint *.js""lint": "jshint **/*.js"下面代码中,*示意任意文件名,**示意任意一层子目录。 脚本传参-- 后的内容会原样传给命令。 $ npm run command1 -- param或者再封装一个命令: "command1": "node test.js","command2": "npm run command1 -- param"$ npm run command2执行程序并行执行: ...

February 25, 2021 · 1 min · jiezi

关于node.js:NPM-的包管理

NPM 装置模块$ npm install express装置后即可引入应用: var express = require('express');NPM 卸载模块$ npm uninstall express$ npm lsNPM 更新模块$ npm update expressNPM 搜寻模块$ npm search expressNPM 革除缓存npm cache clearNPM 装置模块的两种形式全局装置装置的包保留在系统目录下,次要用于全局须要应用的模块。 npm install express -g查看所有全局装置的模块: $ npm list -g本地装置装置的包保留在我的项目目录下,次要用于我的项目须要应用的模块。 npm install express查看所有本地装置的模块: $ npm list

February 25, 2021 · 1 min · jiezi

关于node.js:Nodejs-和-NPM-的安装和配置

Node.js 的装置CentOS装置:$ dnf module list nodejs$ dnf module install nodejs:14Windows 装置:https://nodejs.org/en/download/ 查看装置版本: $ node -vNPM 的装置Node.js 内置了 NPM 包管理工具,无需独自装置。 查看装置版本: $ npm -v降级 npm 到最新版本: $ npm install npm -g配置 NPM 应用淘宝镜像源长期应用$ npm install express --registry https://registry.npm.taobao.org永恒应用$ npm config set registry https://registry.npm.taobao.org$ npm config get registry$ npm info express复原为原来的官网地址 $ npm config set registry https://registry.npmjs.org应用 cnpm 代替$ npm install cnpm -g --registry=https://registry.npm.taobao.org$ cnpm install express

February 24, 2021 · 1 min · jiezi

关于node.js:vscode韭菜盒子批量导入股票自选

1.由来下班不摸鱼还叫下班吗,一天不盯盘就浑身不得劲,然而也不能一天到晚抱着个手机。经共事举荐,应用了vscode的韭菜盒子,的确是个好货色呃,找了半天,怎么没有批量导入自选的性能,难道要我手动把一百多个自选增加到韭菜盒子里吗...还是得想个主动批量导入的办法 2.过程2.1大体思路1.先从西方财产导出自选股csv文件2.写个node脚本解决csv文件3.导入到韭菜盒子的配置文件中 2.2导出东财app右键点击导出所有自选文件为csv 2.3解决在excel外面关上,把所有数据粘贴进去在这个网站先把数据转换成jsonCSV转JSON而后就发现json不能用呀 如同不是很规范 没事建个txt文件,咱们间接读文本,把它写成这种一行一行的 写个node脚本 一行一行的读,把股票代码读出来const fs = require('fs')const readline = require('readline');const fileStream = fs.createReadStream('./1.txt');const outStream = fs.createWriteStream('./2.txt');const rl = readline.createInterface({ input: fileStream, output: outStream,});// 逐行读取rl.on('line', (lineData) => { if (!lineData) { return } const code = lineData.split(',')[1].split(':')[1] let _code = code.slice(2,-1) let regsz = /^(0|3|1)/ let regsh = /^(6)/ if(regsz.test(_code)) { //专门按韭菜盒子的要求,增加前缀 _code = `sz${_code}` outStream.write(`"${_code}",\n`) }else if(regsh.test(_code)){ _code = `sh${_code}` outStream.write(`"${_code}",\n`) }else{ return }})// 监听读取实现rl.on('close', () => { console.log('end')})2.4导入拿到2.txt外面的货色,复制到韭菜盒子的配置文件中即可 ...

February 23, 2021 · 1 min · jiezi

关于node.js:npm错误超出调用栈

谬误内容npm ERR! Maximum call stack size exceedednpm ERR! A complete log of this run can be found in:npm ERR! /Users/jiangshuanglong/.npm/_logs/2021-02-22T04_27_34_740Z-debug.log解决办法降级npm版本npm i npm -g

February 22, 2021 · 1 min · jiezi

关于node.js:关于码云Gitee和GitHub的基本操作

git是什么?还是科普一下吧:Git是一个开源的分布式版本控制系统,能够无效、高速的解决从很小到十分大的我的项目版本治理(来自我大百度) 当初越来越多的公司曾经应用git来进行我的项目的版本治理,,应用起来特地的不便,多人开发效率也大大提高,然而首先先有一个git仓库,git仓库分为两类:公有仓库和共有仓库,GitHub因为是开源的,貌似仓库是公开的,窃密的貌似要rmb,码云能够用公有仓库。 码云和github的区别:码云国内,GitHub国外。GitHub是全英文并且用户基数多,出名的库也多;而码云全是中文,且大部分用户是国人,优良的库绝对于GitHub比拟少。 对于集体而言,码云和 GitHub 并不是一种非此即彼的抉择(然而码云对English不是很优良的童鞋还是很敌对的)这两个网站的性能和操作比拟相似,我这里简略的介绍一下本地与近程的提交。 废话不多说,间接上图文(嘿嘿)首先关上链接注册账号:码云Gitee Github 这里我注册好了,就不注册了,另外Gitee和GitHub第一次配置的时候须要配制密钥,我这么配好了,就不赔了,须要的配置形式的同学能够留言。 # Gitee 1 创立新的仓库,ps:这里有个坑,一会整一下。2 进入新创建的仓库,关上终端,进入你要提交的我的项目外面,上图!3 这里在进行 git push -u origin master的时候我报了个错如下:4 通过钻研发现11月份是网站把邮箱的平安降级了,详情能够百度,代码提不下来了,解决如下:5 解决了之后再运行 终端:6 这时候咱们的我的项目基本上就曾经在Gitee上存好了,而后接下来咱们用vs code这个编辑器搞一下。这外面有一些性能,能够代替终端中的一下指令,还是比拟好用的。上面我贴一些罕用的git终端指令 git init //初始化git暗藏文件git status //查看提交状态git add . git commit -m ‘xxx’ //这两个是将咱们的代码放到暂存区期待上传到近程仓库git remote add origin https:xxx.gitgit push -u origin master // 通过这两个命令将咱们的代码提交到近程仓库git clone https:仓库地址 //将咱们的代码从近程仓库,拷贝内容到本d地git pull //将近程的仓库的内容同步到本地7 总结:vs code 能够提供咱们去操作近程仓库的办法,还是比拟不便的,还有下面的例子也要留神,多人同时开发的话肯定要先git pull同步最新的代码,防止前面git push的时候抵触。 GitHub1 Github和 Gitee的操作差不多,这里就不这么细了。也还是先注册,配置密钥,我这里弄好了就不弄了,须要的童鞋要搞一下。2 首先也是创立一个新的仓库,只不过是英文的,哈哈,不多说,上图!持续!这里有一个小坑,大家留神一下 把main 改成master 3 基本上就这样,后续再更新、、、

February 20, 2021 · 1 min · jiezi

关于node.js:Mac下全局安装yarn-没权限处理方式

间接全局装置yarn时报没有权限的谬误 在 npm i -g yarn 时 在后面加上sudo也没有权限拜访 yarn --vresion 用这个形式就能够 sudo -snpm install -g yarn

February 20, 2021 · 1 min · jiezi

关于node.js:译NodeJS-and-Good-Practices

引子文章 《The Single Responsibility Principle》 是从《NodeJS and Good Practices》外面看到的,持续翻译记录。 翻译原文:NodeJS and Good Practices OriginMy GitHub注释软件总是处于随时变动中,而有助于掂量代码品质的一个方面是改变代码的容易水平。但为什么会这样呢? ...如果你胆怯扭转某些货色,那么它显然设计得很蹩脚。— Martin Fowler 关注点和责任拆散(Separation of concerns and responsibilities)“将因同样起因而扭转的事件集中起来。将因不同起因而扭转的事件离开。” 无论是函数、类还是模块,它们都能够利用繁多责任准则和关注点拆散。从架构开始,基于这些准则进行软件设计。 架构(Architecture)在软件开发中,责任 是独特致力于实现的工作,例如:在应用程序中示意产品的概念、解决网络申请、数据库中用户长久化等等。 留神到这三项责任不属于同一类别吗?这是因为它们属于不同的档次,这些档次能够划分为不同的概念。根据上述示例,“在数据库中用户长久化”波及“用户”概念,也波及与数据通信的层。 一般来说,与上述概念相干的架构往往分为四层:定义域(domain)、利用(application)、基础设施(infrastructure)和输出(input interfaces)。 定义域层在这一层中,咱们能够定义有实体和业务规定作用的单元,它们与咱们的定义域有间接的关系。例如,在用户和团队的应用程序中,咱们可能有一个 User 实体、一个 Team 实体和一个 JoinTeamPolicy 来答复用户是否可能退出给定的团队。 这是咱们软件中最独立和最重要的一层,应用层能够应用它来定义用例。 应用层应用层定义了咱们应用程序的理论行为,因而负责执行定义域层中各单元之间的交互。例如,咱们能够有一个 JoinTeam 用例 ,它接管 User 和 Team 的实例并把它们传递给JoinTeamPolicy ;如果用户能够退出,它将长久化的责任委托给基础设施层。 应用层还能够用作基础设施层的适配器 。假如咱们的应用程序能够发送电子邮件;负责与电子邮件服务器间接通信的类(让咱们称它为 MailChimpService )属于基础设施层,但理论发送电子邮件的类(EmailService)属于应用层 ,并且在外部应用 MailChimpService 。因而,咱们应用程序的其余部分不晓得具体实现细节——它只晓得 EmailService 可能发送电子邮件。 基础设施层这是所有层中最底层,是咱们应用程序所有延长的边界:数据库、电子邮件服务、队列引擎等。 多层 应用程序的一个常见个性,是应用存储库模式与数据库或其它一些内部长久化服务(如 API)通信。存储库对象实质上被视为汇合,应用它们的层(定义域层 和应用层 )不须要晓得底层是那种长久化技术(相似于咱们的电子邮件服务示例)。 这里的想法是,存储库接口属于定义域层,而实现则属于基础设施层,即定义域只晓得存储库承受的办法和参数。这使得这两个层更加灵便,即便在测试方面也是如此!因为 JavaScript 没有实现接口的概念,咱们能够设想本人的接口,并基于基础设施层创立一个具体的实现。 输出层这个层蕴含咱们应用程序的所有入口,比方控制器、CLI、websockets、图形用户界面(对于桌面应用程序)等等。 它不应该对业务规定、用例、长久化技术有任何理解,甚至不应该对其它类型的逻辑有任何理解!它应该只接管用户输出(比方URL参数),将其传递给用例,最初返回响应给用户。 NodeJS 与关注点拆散好了,在所有这些实践之后,如何将这些实践利用到 Node 应用程序?诚实说,多层架构中应用的一些模式非常适合 JavaScript 世界! ...

February 16, 2021 · 2 min · jiezi

关于node.js:Puppeteer爬取Youtube列表页面

Puppeteer 是基于nodejs的爬取工具,玲珑轻便,它提供各种API 来管制Chrome 或Chromium 浏览器,用来做为测试、爬虫都相当适合,并且所提供的API 语法浅显易懂。Puppeteer 地址 通过几句简略的语句,咱们能够是用Puppeteer爬取Youtube视频列表页面中的视频内容 const puppeteer = require('puppeteer')const browser = await puppeteer.launch({args: ['--no-sandbox']})const page = await browser.newPage()await page.goto('https://www.youtube.com/channel/UChaPcyq-uGOio8S_7-bguZA')const html = await page.content()await browser.close()爬取的网页内容通过简略的筛选就能失去视频内容。 具体的我的项目请看视频: https://www.bilibili.com/vide... https://www.bilibili.com/vide...

February 13, 2021 · 1 min · jiezi

关于node.js:jenkinsdocker-实现前端和nodejs服务端自动化发布

前言古代软件工程都强调继续集成的能力,而继续集成的一个重要组成部分继续部署。也就是本文的重点,自动化部署。本文会从零开始讲述每个环节的原理和实现办法。 jenkins+docker装置装置docker只须要一句运行命令即可装置: curl -fsSL https://get.docker.com | bash -s docker --mirror Aliyun输出命令后回车期待一会看到上面的信息就是装置实现了: root@iZwz92akl2vtt9nu4w6lq7Z:~# curl -fsSL https://get.docker.com | bash -s docker --mirror Aliyun# Executing docker install script, commit: 3d8fe77c2c46c5b7571f94b42793905e5b3e42e4+ sh -c 'apt-get update -qq >/dev/null'+ sh -c 'DEBIAN_FRONTEND=noninteractive apt-get install -y -qq apt-transport-https ca-certificates curl >/dev/null'+ sh -c 'curl -fsSL "https://mirrors.aliyun.com/docker-ce/linux/ubuntu/gpg" | apt-key add -qq - >/dev/null'Warning: apt-key output should not be parsed (stdout is not a terminal)+ sh -c 'echo "deb [arch=amd64] https://mirrors.aliyun.com/docker-ce/linux/ubuntu focal stable" > /etc/apt/sources.list.d/docker.list'+ sh -c 'apt-get update -qq >/dev/null'+ '[' -n '' ']'+ sh -c 'apt-get install -y -qq --no-install-recommends docker-ce >/dev/null'+ sh -c 'docker version'Client: Docker Engine - Community Version: 20.10.3 API version: 1.41 Go version: go1.13.15 Git commit: 48d30b5 Built: Fri Jan 29 14:33:21 2021 OS/Arch: linux/amd64 Context: default Experimental: trueServer: Docker Engine - Community Engine: Version: 20.10.3 API version: 1.41 (minimum version 1.12) Go version: go1.13.15 Git commit: 46229ca Built: Fri Jan 29 14:31:32 2021 OS/Arch: linux/amd64 Experimental: false containerd: Version: 1.4.3 GitCommit: 269548fa27e0089a8b8278fc4fc781d7f65a939b runc: Version: 1.0.0-rc92 GitCommit: ff819c7e9184c13b7c2607fe6c30ae19403a7aff docker-init: Version: 0.19.0 GitCommit: de40ad0If you would like to use Docker as a non-root user, you should now consideradding your user to the "docker" group with something like: sudo usermod -aG docker your-userRemember that you will have to log out and back in for this to take effect!WARNING: Adding a user to the "docker" group will grant the ability to run containers which can be used to obtain root privileges on the docker host. Refer to https://docs.docker.com/engine/security/security/#docker-daemon-attack-surface for more information.执行一下查看版本的命令再次确认装置胜利: ...

February 12, 2021 · 3 min · jiezi

关于node.js:nginx的安装配置使其可以访问nodejs

在windows下装置非常简单在http://nginx.org/en/download.... 下载压缩包(只有1.6M)下载后解压,而后执行nginx.exe文件,OK! 在浏览器里输出 http://localhost:80/ 呈现nginx欢送界面! 启动nginx:start nginx或nginx.exe进行nginx:nginx.exe -s stop或nginx.exe -s quit 能够写个stop.bat批处理文件: nginx.exe -s stop留神:第一次运行stop的时候会报个错:nginx: [error] CreateFile() "E:\nginx\nginx-1.9.3/logs/nginx.pid" failed意思是log文件未创立,执行上面的语句创立即可: nginx -c conf/nginx.conf装置nginx后,就能够反向代理拜访咱们的nodejs啦!这也是nginx的次要用法。 批改nginx的conf目录下的nginx.conf文件来配置咱们的网站! 看下nginx.conf的默认配置 server { listen 80; server_name localhost; location / { root html; index index.html index.htm; } ...listen 80 示意nginx监听的是80端口,也就是网站的默认拜访端口。server_name 能够设为域名或IP。location里的root示意根目录,默认为nginx目录下的html子目录。index示意如果不指定网页文件名,默认拜访的网页是index.html。 咱们当初指定一个路由到nodejs的get申请:在配置文件里减少如下配置: location /getcode/ { proxy_pass http://127.0.0.1:6060/code/; }proxy_pass指向的就是代理路由,即如果咱们在浏览器中拜访http://localhost/getcode/ ,nginx就会指向拜访http://127.0.0.1:6060/code/ 。 下一步咱们在nodejs里应用express来回应这一get申请: var app = express();app.get('/code', function(req, res) { res.send('hello code!'); res.end()})最终咱们返回的页面后果为: *在理论的运行环境下部署,server_name设置为外网IP,proxy_pass设置为内网IP,这样实现了从外网IP到内网IP的映射!

February 8, 2021 · 1 min · jiezi

关于node.js:nodejskoa以流的形式返回数据

需要背景: 我的项目中有多处下载数据的中央,有时候遇到几百万条数据,一口气返回的话,可能会导致内存不够用。 需要:是不是有一种办法,能让我循环每次取一点数据返回? 解决方案:目前想到两种—— 一种是node端应用 stream 形式返回,前端用window.location.href的形式关上后端接口。 另一种是后端提供分页接口,前端应用 StreamSaver.js(文件大小无限度) 或 FileSaver.js(文件大小受限于前前端可用内存和Blob容许的最大值即2G) 保留文件。 两种办法各有劣势,按需选取。 计划长处毛病服务端stream只发动一次http申请如果接口有可能会返回json让前端判断是否下载,则前端会很难。如果运维不违心加长网关超时,也是一个毛病前端stream前端能够做更细的判断发动屡次http申请本文先介绍第一种,另一种另起一篇文章。 服务端stream查阅koa的文档,只须要 ctx.body= 左边的值类型是 ReadableStream 即可。那么能够用 stream.Readable,因为我不习惯stream.Readable自身的用法,所以我封装了一个繁难的函数: /** * 创立一个可读 stream ,循环调用 getData 函数获取数据,当 该函数 返回 null 时完结,如果返回undefined,会认为是返回空字符串 * @param getData size参数是用于参考单次返回多少数据,不是说要严格依照这个。size单位应该是字节。必须返回的是 utf8 编码的 * */ function createReadableStream( getData: (size: number) => Promise<string | null>) { return new stream.Readable({ async read(size) { while (true) { let data = null try { data = await getData(size) } catch (e) { console.error('[h-node-utils-error createReadable]:', e) } const goContinue = this.push(data, 'utf8') if (!goContinue || data === null) { break } } }, })}应用办法: ...

February 3, 2021 · 1 min · jiezi

关于node.js:koa2用中间件koastaticrouter-搭建静态资源服务器实现多级路由加载静态资源

源码及应用阐明 Git仓库装置npm install koa-static-routerUsage单个路由const static = require('koa-static-router'); app.use( static({ dir, //动态资源目录对于绝对入口文件index.js的门路 route //路由命名 }) )多个路由抉择多个路由时,请确保路由长度雷同 '/static/' - >路由长度 = 1 '/static/image1/' - >路由长度 =2 const static = require('koa-static-router');app.use( static([ { dir, //动态资源目录对于绝对入口文件index.js的门路 router //路由命名 },{ dir, router } ]))Demogit clonecd koa-static-routernpm install npm start拜访 localhost:3000/public/image/dir/1.png 拜访 localhost:3000/static/image/dir/2.png const Koa = require('koa')const app = new Koa()const static = require('koa-static-router');// 单个路由// app.use(static({// dir:'public',// router:'/static/' //路由长度 =1// }))//多个路由app.use(static([ { dir:'public', //动态资源目录对于绝对入口文件index.js的门路 router:'/public/image/' //路由命名 路由长度 =2 },{ dir:'static', //动态资源目录对于绝对入口文件index.js的门路 router:'/static/image/' //路由命名 路由长度 =2 }]))app.use( async ( ctx ) => { ctx.body = 'hello world'})app.listen(3000, () => { console.log('build success')})

February 3, 2021 · 1 min · jiezi

关于node.js:node端ejs中使用模块变量

前言ejs在默认状况下只是一个出现工具,只是负责根据传入的参数进行模板渲染。然而,在应用过程中(hexo-renderer-ejs),我心愿在模板中应用require引入内部模块,应用__dirname,__filename变量,即便这个用法是不举荐的。 做法通过批改ejs的源码来实现反对,我应用的版本是ejs@^2.6.1。 关上node_modules/ejs/lib/ejs.js文件,在结尾增加: 47 var fs = require('fs');48 var path = require('path');49 var utils = require('./utils');50 + var { Module, createRequireFromPath } = require('module')找到Template.prototype中的compile函数,批改其中的returnedFn: 675 var returnedFn = opts.client ? fn : function anonymous(data) { - var include = function (path, includeData) { + var include = function (_path, includeData) { var d = utils.shallowCopy({}, data); if (includeData) { d = utils.shallowCopy(d, includeData); } const customModule = new Module() + d.__filename = getIncludePath(_path, opts) + customModule.id = d.__dirname = path.dirname(d.__filename) + d.module = customModule + d.require = createRequireFromPath(d.__filename) - return includeFile(path, opts)(d); + return includeFile(_path, opts)(d); }; + const customModule = new Module() + customModule.id = customModule.path = data.__dirname = path.dirname(opts.filename) + data.module = customModule + data.__filename = opts.filename + data.require = createRequireFromPath(data.__filename) return fn.apply(opts.context, [data || {}, escapeFn, include, rethrow]);695 };如果node的版本是 v12.2.0或以上,将createRequireFromPath改为createRequire 参考文档

February 3, 2021 · 1 min · jiezi

关于node.js:mongoose犯错记录

合作伙伴提了一个问题,就是当他删除父级节点的时候,接口会返回此父级节点下的所有字节点(尽管不在页面中显示),他心愿不要接口中不要有这些.我用递归的办法,找到字节点并删除,但因为用findOne,导致只删除了一个字节点.正确做法是用find,找到所有,并循环删除

February 3, 2021 · 1 min · jiezi

关于node.js:不要在nodejs中阻塞event-loop

简介咱们晓得event loop是nodejs中事件处理的根底,event loop中次要运行的初始化和callback事件。除了event loop之外,nodejs中还有Worker Pool用来解决一些耗时的操作,比方I/O操作。 nodejs高效运行的秘诀就是应用异步IO从而能够应用大量的线程来解决大量的客户端申请。 而同时,因为应用了大量的线程,所以咱们在编写nodejs程序的时候,肯定要特地小心。 event loop和worker pool在nodejs中有两种类型的线程。第一类线程就是Event Loop也能够被称为主线程,第二类就是一个Worker Pool中的n个Workers线程。 如果这两种线程执行callback破费了太多的工夫,那么咱们就能够认为这两个线程被阻塞了。 线程阻塞第一方面会影响程序的性能,因为某些线程被阻塞,就会导致系统资源的占用。因为总的资源是无限的,这样就会导致解决其余业务的资源变少,从而影响程序的总体性能。 第二方面,如果常常会有线程阻塞的状况,很有可能被歹意攻击者发动DOS攻打,导致失常业务无奈进行。 nodejs应用的是事件驱动的框架,Event Loop次要用来解决为各种事件注册的callback,同时也负责解决非阻塞的异步申请,比方网络I/O。 而由libuv实现的Worker Pool次要对外裸露了提交task的API,从而用来解决一些比拟低廉的task工作。这些工作包含CPU密集性操作和一些阻塞型IO操作。 而nodejs自身就有很多模块应用的是Worker Pool。 比方IO密集型操作: DNS模块中的dns.lookup(), dns.lookupService()。 和除了fs.FSWatcher()和 显式同步的文件系统的API之外,其余多有的File system模块都是应用的Worker Pool。 CPU密集型操作: Crypto模块:crypto.pbkdf2(), crypto.scrypt(), crypto.randomBytes(), crypto.randomFill(), crypto.generateKeyPair()。 Zlib模块:除了显示同步的API之外,其余的API都是用的是worker pool。 一般来说应用Worker Pool的模块就是这些了,除此之外,你还能够应用nodejs的C++ add-on来自行提交工作到Worker Pool。 event loop和worker pool中的queue在之前的文件中,咱们讲到了event loop中应用queue来存储event的callback,实际上这种形容是不精确的。 event loop实际上保护的是一个文件描述符汇合。这些文件描述符应用的是操作系统内核的 epoll (Linux), kqueue (OSX), event ports (Solaris), 或者 IOCP (Windows)来对事件进行监听。 当操作系统检测到事件筹备好之后,event loop就会调用event所绑定的callback事件,最终执行callback。 相同的,worker pool就真的是保留了要执行的工作队列,这些工作队列中的工作由各个worker来执行。当执行结束之后,Woker将会告诉Event Loop该工作曾经执行结束。 阻塞event loop因为nodejs中的线程无限,如果某个线程被阻塞,就可能会影响到整个应用程序的执行,所以咱们在程序设计的过程中,肯定要小心的思考event loop和worker pool,防止阻塞他们。 event loop次要关注的是用户的连贯和响应用户的申请,如果event loop被阻塞,那么用户的申请将会得不到及时响应。 因为event loop次要执行的是callback,所以,咱们的callback执行工夫肯定要短。 ...

February 2, 2021 · 3 min · jiezi

关于node.js:下面四款主题风格不知哪款能入你的法眼

CabloyJS除了继承Framework7的红色主题和暗色主题,还内置了两款自定义主题:风信子、璀璨, 不知哪款能入你的法眼? 1. 红色主题 2. 暗色主题 3. 风信子 4. 璀璨 带侧边栏 挪动端布局 相干链接官网: https://cabloy.com/GitHub: https://github.com/zhennann/cabloy

February 1, 2021 · 1 min · jiezi

关于node.js:小程序云开发入门

云函数(能够了解为一般开发中的接口的实现)cloudfunctions目录右键新建node.js云函数例如helloWord须要在终端里 去装置云函数helloWordcd cloudfunctions/helloWordnpm i装置实现后,这时的云函数就是能够应用了(函数的内容是用户的根本信息)。能够在小程序index.js的onload生命周期里去调试应用一下(调用云函数就像是调用接口)。const result = await wx.cloud.callFunction({ name:'helloWord'})console.log(result)应用云函数进行数据库的查问和批改数据库反对async/await操作在进行数据库add时 须要新建一个数据库汇合(表)也无需定义表构造db.collection 能够进行表的查问操作db.command 能够进行简单的子表查问.where 前面跟查问条件.get 是查问后果const db = wx.cloud.database() await db.collection('users').where({ _openid: 'user-open-id'}).get({ success: function(res) { console.log(res.data) }})

January 31, 2021 · 1 min · jiezi

关于node.js:NodeJS之Promise

原文链接:浅谈NodeJS之Promise NodeJS里为解决同步执行的问题,常常须要嵌套调用,Promise就是解决这一问题的,其实微信小程序开发也有同样的问题,也提供了promise形式的解决办法。 以下是援用的原文: 啥是Promise?Promise是一个构造函数,办法有all、reject、resolve这几个,原型上有then、catch等办法。那么new Promise 进去的对象必定就有then、catch办法。跟着我一步一步学习吧。本文能让你对Promise有一个颠覆的意识。 让咱们new一个吧: var promise = new Promise(function(resolve, reject){ //异步操作 setTimeout(function(){ console.log('执行结束!'); resolve('xxx'); }, 2000);});执行异步操作,2秒后输入“执行结束!”,并调用resolve办法。 Promise的构造函数接管一个参数,是函数,并且传入两个参数:resolve,reject,别离示意异步操作执行胜利后的回调函数和异步操作执行失败后的回调函数。其实依照规范来讲,resolve是将Promise的状态置为fullfiled,reject是将Promise的状态置为rejected。 以上咱们new了一个对象,并没有调用它,传进去的函数就曾经执行了,所以咱们用Promise的时候个别是包在一个函数中,在须要的时候去运行这个函数,如: function runAsync(){ var promise = new Promise(function(resolve, reject){ setTimeout(function(){ console.log('执行结束); resolve('xxx'); }, 2000); }); return promise; }runAsync();包装函数的作用和resolve的作用 执行这个函数咱们能失去了一个Promise对象,即包装好的函数最初,会return出Promise对象,。还记得Promise对象上有then、catch办法吧?这就是弱小之处了,看上面的代码: runAsync().then(function(data){ console.log(data); //这里用传过来的数据做其余操作});在runAsync()的返回上间接调用then办法,then接管一个参数,是函数,并且会拿到咱们在runAsync中调用resolve时传的的参数。运行这段代码,2秒后输入“执行结束”,紧接着输入“xxx”。 then外面的函数就跟咱们平时的回调函数一个意思,可能在runAsync这个异步工作执行实现之后被执行,这就是Promise的作用,艰深讲,就是把原来的回调写法分离出来,在异步操作执行完后,用链式调用的形式执行回调函数。 如果只有一次调用,也能够这么写,成果一样: function runAsync(callback){ setTimeout(function(){ console.log('执行结束'); callback('xxx'); }, 2000);} runAsync(function(data){ console.log(data);});那么有多层回调该怎么办?Promise的劣势在于,能够在then办法中持续写Promise对象并返回,而后持续调用then来进行回调操作。 链式操作的用法所以,从外表上看,Promise只是可能简化层层回调的写法,而本质上,Promise的精华是“状态”,用保护状态、传递状态的形式来使得回调函数可能及时调用,它比传递callback函数要简略、灵便的多。所以应用Promise的正确场景是这样的: function runAsync1(){ var promise = new Promise(function(resolve, reject){ setTimeout(function(){ console.log('异步1实现'); resolve('xxx1'); }, 1000); }); return promise ; }function runAsync2(){ var promise = new Promise(function(resolve, reject){ setTimeout(function(){ console.log('异步2实现'); resolve('xxx2'); }, 2000); }); return promise ; }function runAsync3(){ var promise = new Promise(function(resolve, reject){ setTimeout(function(){ console.log('异步3实现'); resolve('xxx3'); }, 2000); }); return promise ; }runAsync1().then(function(data){ console.log(data); return runAsync2();}).then(function(data){ console.log(data); return runAsync3();}).then(function(data){ console.log(data);});这样可能按程序,每隔两秒输入每个异步回调中的内容,在runAsync2中传给resolve的数据,能在接下来的then办法中拿到。运行后果如下: ...

January 30, 2021 · 2 min · jiezi

关于node.js:使用nodejs构建Docker-image最佳实践

简介docker容器的呈现,彻底的扭转了应用程序的运行形式,而nodejs同样的也颠覆了后端应用程序的开发模式。两者联合起来,就会产生意想不到的作用。 本文将会以一个罕用的nodejs程序为例,剖析怎么应用docker来构建nodejs image. 筹备nodejs应用程序一个规范的nodejs程序,须要一个package.json文件来形容应用程序的元数据和依赖关系,而后通过npm install来装置利用的依赖关系,最初通过node app.js来运行程序。 本文将会创立一个简略的koa应用程序,来阐明docker的应用。 首先创立package.json文件: { "name": "koa-docker", "description": "怎么将nodejs koa程序打包成docker利用", "version": "0.0.1", "dependencies": { "ejs": "^2.5.6", "fs-promise": "^2.0.3", "koa": "^2.2.0", "koa-basic-auth": "^2.0.0", "koa-body": "^4.0.8", "koa-compose": "^4.0.0", "koa-csrf": "^3.0.6", "koa-logger": "^3.0.0", "@koa/router": "^8.0.5", "koa-session": "^5.0.0", "koa-static": "^3.0.0", "koa-views": "^6.0.2" }, "scripts": { "test": "NODE_ENV=test mocha --harmony --reporter spec --require should */test.js", "lint": "eslint ." }, "engines": { "node": ">= 7.6" }, "license": "MIT"}下面的package.json文件制订了我的项目的依赖。 接下来,咱们须要应用npm install来装置我的项目的依赖,装置好的我的项目依赖文件将会放在本地的node_modules文件夹中。 而后咱们就能够编写服务程序了: ...

January 29, 2021 · 2 min · jiezi

关于node.js:nodestream流

stream流:将数据的传输看作是水流,分段传输,能更好的管制,提高效率。所有的 Stream 对象都是 EventEmitter 的实例分类:包含了读,写,边读边写等数据流。eg:fs的文件读写等api; 用读文件的数据流据举例子: //自主定义读文件的流let freadStream = fs.createReadStream('./test.txt',{ //每次读取字节数 highWaterMark:3, //读取模式 flags:'r', //默认 'r' autoClose:true, //默认读取结束后主动敞开 start:0, //读取文件开始地位 // end:3, //流是闭合区间 蕴含start也含end encoding:'utf8' //默认null})//下面创立了一个读取test.data的数据流,当初让他运行起来freadStream.on('open',()=>{ console.log('流开始关上文件');})freadStream.on('data',(e)=>{ console.log('继续有数据被读取进去:',e);})freadStream.on('end',()=>{ console.log("数据读取实现,没有流了");})```

January 28, 2021 · 1 min · jiezi

关于node.js:Nodejs-Koa2框架中使用Swagger

yarn add koa2-swagger-ui swagger-jsdocserver.js const Koa = require('koa')const app = new Koa()const {koaSwagger} = require('koa2-swagger-ui') const swaggerRouter = require('./routes/swagger') // ......app.use(swaggerRouter.routes()).use(swaggerRouter.allowedMethods())const swaggerOption = { routePrefix: '/swagger/index.html', // host at /swagger instead of default /docs swaggerOptions: { url: '/swagger/swagger.json' // example path to json 其实就是之后swagger-jsdoc生成的文档地址 } }app.use(koaSwagger(swaggerOption))app.listen(3000)./routes/swagger.js const Router = require('koa-router')const path = require('path')const swaggerJSDoc = require('swagger-jsdoc')const router = new Router({ prefix: '/swagger' // 路由前缀})const swaggerDefinition = { info: { title: 'API 接口', version: 'v1' }}const options = { swaggerDefinition, apis: [path.join(__dirname, './docs/*.js')] // 写有注解的router的寄存地址, 最好 path.join()}const swaggerSpec = swaggerJSDoc(options)// 通过路由获取生成的注解文件router.get('/swagger.json', async function (ctx) { ctx.set('Content-Type', 'application/json') ctx.body = swaggerSpec})module.exports = router./routes/doc/api.js ...

January 28, 2021 · 1 min · jiezi

关于node.js:nodejs的调试debug

简介对于开发者来说,在开发应用程序的过程中,往往为了开发不便和解决bug须要借助于编程语言的调试性能。一般来说咱们须要借助于弱小IDE的调试性能来实现这项工作。nodejs也不例外。 明天咱们来具体介绍一下如何调试nodejs程序。 开启nodejs的调试还记得之前咱们讲到的koa程序吗?本文将会以一个简略的koa服务端程序为例,来开展nodejs的调试。 先看下一个简略的koa服务app.js: const Koa = require('koa');const app = module.exports = new Koa();app.use(async function(ctx) { ctx.body = 'Hello World';});if (!module.parent) app.listen(3000);下面的程序开启了3000端口,建设了一个http服务。每次申请的时候,都会返回hello World,十分的简略。 要想运行下面的程序,咱们须要执行node app.js。 这会执行app.js然而并不会开启调试性能。 怎么进行调试呢? 咱们须要加上 --inspect 参数: node --inspect app.js下面的代码将会开启nodejs的调试性能。 咱们看下输入后果: Debugger listening on ws://127.0.0.1:9229/88c23ae3-9081-41cd-98b0-d0f7ebceab5aFor help, see: https://nodejs.org/en/docs/inspector后果通知了咱们两件事件,第一件事件就是debugger监听的端口。默认状况下将会开启127.0.0.1的9229端口。并且调配了一个惟一的UUID以供辨别。 第二件事件就是通知咱们nodejs应用的调试器是Inspector。 Inspector是nodejs 8之后引入的,如果是在nodejs 7之前,那么应用的是legacy debugger。 调试的安全性如果debugger连贯到了nodejs运行环境中,如果有歹意攻击者的话,这个歹意攻击者能够在nodejs环境中运行任意代码。这会给咱们的程序带来很大的安全隐患。 所以咱们肯定要留神调试的安全性。一般来说,咱们不倡议进行近程调试。 默认状况下 --inspect 绑定的是127.0.0.1,这样就只容许本地程序拜访。并且任何本地运行的程序都有权限进行该程序的调试。 如果咱们真的想将debug程序裸露给内部程序的话,那么能够指明本机的外网IP地址或者0.0.0.0(示意任何地址,无限度),这样近程机子就能够进行近程调试了。 如果咱们想进行平安的remote debug该怎么解决呢? 首先,咱们要开启本地的debug: node --inspect app.js而后咱们能够搭建一个ssh隧道,将本地的9221端口映射到近程服务器的9229端口: ssh -L 9221:localhost:9229 user@remote.example.com这样咱们就能够通过连贯本地的9221端口,进行近程调试了。 应用WebStorm进行nodejs调试JetBrains出品的WebStorm堪称是开发nodejs的利器,WebStorm自带有debug选项,如果开启该选项,则会在后盾开启 --inspect: 应用WebStorm来进行调试和应用IDEA来进行java程序调试相似,这里就不多介绍了。 应用Chrome devTools进行调试应用Chrome devTools进行调试的前提是咱们曾经开启了 --inspect模式。 ...

January 27, 2021 · 1 min · jiezi

关于node.js:工程化-利用-webhooks-进行集成

Webhooks allow you to build or set up integrations在日常开发过程中,你肯定会有这样的困扰:有一些流程化的工作,甚至是一些很小的改变,都会经验:开发 - 测试 - 提交 - 打包 - 上传 - 编译 - 公布等过程,频繁的反复,大大地升高了咱们开发的乐趣! 为此,Git 通过提供 webhooks 来使咱们具备可集成的能力。艰深来说,就是 Github 针对你的一系列流动,提供了一些“钩子”,当你进行某项流动时(比方:新建一个 tag),Github 会被动向你的服务器发送一个申请,告诉你指定事件正在被触发,通过对申请进行捕捉和剖析,你能够通过脚本等形式在服务器上执行后续步骤。 关键点: 配置 web hooks.Payload URL 时,留神 Github 目前不反对转发服务(Redirect),如果你在服务器通过 nginx 配置了转发,且配置 Payload URL 为转发域名,则 Github 会返回 502,解决方案:裸露 host:port/path留神 Github 对 secret 的加密形式和比照验证 Config webhooks首先,咱们须要在 Github 上进行设置:服务器地址,参数类型,secret,触发事件以及是否激活 设置 Git 须要监听哪些事件来触发 webhooks在服务器内增加路由,用来承受和解决 webhooks 负载(申请)留神:webhooks Payload URL 暂不反对域名转发,能够通过 host:port 来代替 Secret相似 token, 用来通知服务器以后申请来自于 Github ...

January 24, 2021 · 1 min · jiezi

关于node.js:nodejs与微信小程序后台数据库的交互5给定表名查询数据

终于写到查数据这步了,后面都是筹备工作。查问页面page.html: //page.html<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>Document</title></head><body> <input type="text" id="tablename" placeholder="请输出表名"> <button id="bt">提交</button> <h4 id="test"></h4> <script src="page.js"></script></body></html>查问的page.js: //page.jsvar test = document.getElementById('test');var bt = document.getElementById('bt');bt.onclick = function () { var stname = document.getElementById('tablename').value; //生成JSON字符串 var value = "{\"tablename\" : \"" + stname + "\"}"; var xmlHttp = new XMLHttpRequest(); xmlHttp.onreadystatechange=function() { if (xmlHttp.readyState==4 && xmlHttp.status==200) { test.innerHTML = xmlHttp.responseText; var o = JSON.parse(xmlHttp.responseText); var sdata = (o.data)[0].toString(); //data是数组,因为会返回多条记录 var odata = JSON.parse(sdata); console.log(odata.distname); } }; xmlHttp.open('POST', 'http://127.0.0.1:6060/', true); xmlHttp.setRequestHeader("Content-type","application/json;charset=UTF-8"); xmlHttp.send(value); //对象转json};输出要查问的表名并提交。 ...

January 23, 2021 · 2 min · jiezi

关于node.js:express生成token

1.开发环境vue+node2.电脑系统 windows10专业版3.在应用vue+node开发的过程中,在写登录时候咱们会应用到token验证,上面我来分享一下express生成token和简略的应用,心愿对你有所帮忙。4.装置 jsonwebtoken npm install express-jwtnpm install jsonwebtoken --save4-1.express-jwt和jsonwebtoken是什么? express-jwt外部援用了jsonwebtoken,对其封装应用。在理论的我的项目中这两个都须要援用,他们两个的定位不一样。jsonwebtoken是用来生成token给客户端的,express-jwt是用来验证token的。5.在express我的项目中,在public文件夹下新建token.js文件,增加如下代码://用于生成和解析tokenvar jwt = require('jsonwebtoken');var signkey = 'mes_qdhd_mobile_xhykjyxgs';exports.setToken = function (username, userid) { return new Promise((resolve, reject) => { const token = jwt.sign({ name: username }, signkey, { expiresIn: '1h' }); resolve(token); })}exports.verToken = function (token) { return new Promise((resolve, reject) => { var info = jwt.verify(token.split(' ')[1], signkey); resolve(info); })}6.在app.js中进行配置: var vertoken = require('./public/token');app.use(function (req, res, next) { var token = req.headers['authorization']; if (token == undefined) { return next(); } else { vertoken.verToken(token).then((data) => { req.data = data; return next(); }).catch((error) => { return next(); }) } next(createError(404));});app.use(expressJWT({ secret: 'mes_qdhd_mobile_xhykjyxgs', algorithms: ["HS256"]}).unless({ path: ['/index']//除了这个地址,其余的URL都须要验证}));请留神:应用 jwt 可能会报错:algorithms should be set;解决办法:在app.use(expressJWT) 这个配置中增加 algorithms: ["HS256"];报错起因:2020.7.7日jwt更新之后,装置的express-jwt模块会默认为6.0.0版本,更新后的jwt须要在配置中退出algorithms属性,即设置jwt的算法。个别HS256为配置algorithms的默认值:app.use(function (err, req, res, next) { // set locals, only providing error in development if (err.status == 401) { return res.status(401).send('token生效'); } res.locals.message = err.message; res.locals.error = req.app.get('env') === 'development' ? err : {}; // render the error page res.status(err.status || 500); // res.render('error');});7.在接口中应用: ...

January 23, 2021 · 1 min · jiezi

关于node.js:nodejs与微信小程序后台数据库的交互4改进后的html与nodejs通信

在node.js与微信小程序后盾数据库的交互(2)html与node.js的通信 中,咱们实现了html页面通过XMLHttpRequest传递值给node.js服务并返回。 上面咱们对该例子进行改良:page.html文件依然应用咱们在(2)中同样的文件。 //page.jsvar test = document.getElementById('test');var bt = document.getElementById('bt');bt.onclick = function () { //var value = document.getElementById('username').value; var value = {name:"三台子小学",address:"黄河大巷"} var xmlHttp = new XMLHttpRequest(); xmlHttp.onreadystatechange=function() { if (xmlHttp.readyState==4 && xmlHttp.status==200) { test.innerHTML = xmlHttp.responseText; } }; xmlHttp.open('POST', 'http://127.0.0.1:6060/', true); xmlHttp.setRequestHeader("Content-type","application/json;charset=UTF-8"); xmlHttp.send(JSON.stringify(value)); //对象转json};咱们创立一个对象value,并把它转为json字符串发送给6060端口启动的node.js服务。留神:因为传递的是json数据,因而在open和send之间要设置头参数: xmlHttp.setRequestHeader("Content-type","application/json;charset=UTF-8");上面是node.js代码: //app.jsconst hostIp = '127.0.0.1';const apiPort = 6060;var express = require('express');var app = express();var bodyParser = require('body-parser');app.use(bodyParser.json()); // for parsing application/json//allow custom header and CORSapp.all('*',function (req, res, next) { res.header('Access-Control-Allow-Origin', '*'); res.header('Access-Control-Allow-Headers', 'Content-Type, Content-Length, Authorization, Accept, X-Requested-With , yourHeaderFeild'); res.header('Access-Control-Allow-Methods', 'PUT, POST, GET, DELETE, OPTIONS'); if (req.method == 'OPTIONS') { res.sendStatus(200); /让options申请疾速返回/ } else { next(); }});app.post('/', function(req, res) { res.setHeader('Content-Type', 'text/plain;charset=UTF-8'); //返回代理内容 var rtnJSON = JSON.stringify(req.body) console.log("返回数据:"+rtnJSON) res.end(rtnJSON);});var server = app.listen(apiPort, function () { console.log('代理接口,运行于 http://' + hostIp + ':' + apiPort + '/'); })因为XMLHttpRequest发送过去的数据是json格局,因而咱们在express中要应用body-parser来进行解析: ...

January 22, 2021 · 1 min · jiezi

关于node.js:nodejs与微信小程序后台数据库的交互3如何保存accesstoken

参考文章:Node.js access_token的获取、存储及更新https://www.cnblogs.com/hvkco... 和node.js与微信小程序后盾数据库的交互(1)获取accesstoken 相比,咱们前进一步,把获取的accesstoken保留到服务器上。咱们先在node.js的服务启动根目录下创立一个wechat子目录,在该子目录下创立一个名为access_token.json的文件,文件内容为: {"access_token":"","expires_time":0}别离保留accesstoken和过期工夫。 为了下一步应用express设置拜访路由,咱们把node.js与微信小程序后盾数据库的交互(1)获取accesstoken 中的程序修改为应用express的模式: // token.jsconst http = require('http');const request = require('request');var urltool = require('url'); var fs = require('fs'); //引入 fs 模块var accessTokenJson = require('./wechat/access_token');//引入本地存储的 access_tokenconst hostIp = '127.0.0.1';const apiPort = 6060;const data={ appid:"wx4$%#%#%#",//你的微信小程序的appid secret:"@##¥¥……¥##R¥",//你的微信小程序的appsecret grant_type:"client_credential", env:"^%$#^@^" //你的微信小程序的环境参数};var express = require('express');var app = express();app.get('/', function (req, res) { console.log("***************************************") console.log('[申请]来自='+req.url); getAccessToken(res);}) function getAccessToken(res){ //获取以后工夫 var currentTime = new Date().getTime(); const url='https://api.weixin.qq.com/cgi-bin/token?appid='+data.appid+'&secret='+data.secret+'&grant_type='+data.grant_type; var contentText = fs.readFileSync('./wechat/access_token.json','utf-8'); //减少这两句就能够手工批改access_token.json的expires_time来刷新accesstoken accessTokenJson = JSON.parse(contentText) if(accessTokenJson.access_token === "" || accessTokenJson.expires_time < currentTime){ request({ url: url,//申请门路 method: "GET",//申请形式,默认为get headers: {//设置申请头 "content-type": "application/json", }, body: JSON.stringify(data)//post参数字符串 将对象转JSON }, function(error, response, body) { if (!error && response.statusCode === 200) { var obj = JSON.parse(body); //将JSON字符串转为对象 accessTokenJson.access_token = obj.access_token; accessTokenJson.expires_time = new Date().getTime() + (parseInt(obj.expires_in) - 200) * 1000; //更新本地存储的 fs.writeFile('./wechat/access_token.json',JSON.stringify(accessTokenJson),(err)=>{console.log("write OK")}); //编码类型 res.setHeader('Content-Type', 'text/plain;charset=UTF-8'); //容许跨域 res.setHeader('Access-Control-Allow-Origin', '*'); //返回代理内容 var rtnJSON = JSON.stringify(accessTokenJson) console.log("返回数据:"+rtnJSON) res.end(rtnJSON); } }); }else{ res.setHeader('Content-Type', 'text/plain;charset=UTF-8'); //容许跨域 res.setHeader('Access-Control-Allow-Origin', '*'); //返回代理内容 var rtnJSON = JSON.stringify(accessTokenJson) console.log("返回数据:"+rtnJSON) res.end(rtnJSON); }}var server = app.listen(apiPort, function () { console.log('代理接口,运行于 http://' + hostIp + ':' + apiPort + '/'); })微信小程序的accesstoken默认是7200秒过期,因而咱们的程序在7000秒后从新获取新的accesstoken并保留到文件中。启动token.js服务: ...

January 22, 2021 · 1 min · jiezi

关于node.js:nodejs与微信小程序后台数据库的交互1获取accesstoken

微信小程序提供了后盾数据库API接口,怎么实现用网页读取和编辑后盾数据呢?之前看的vue-element-admin太简单了改起来很麻烦,尝试看下用node.js是不是简略些,因为是零根底,所以很多问题都要从头钻研。 1、node.js装置https://www.runoob.com/nodejs... 留神设置零碎path门路 2、最简略的node.js程序运行https://www.runoob.com/nodejs... 是挺有意思的,能够间接创立一个server 3、写一个获取微信后盾accesstoken的服务页面 // token.jsconst http = require('http');const request = require('request');var urltool = require('url'); var querystring = require('querystring');const hostIp = '127.0.0.1';const apiPort = 6060;const data={ appid:"wx4$%#%#%#",//你的微信小程序的appid secret:"@##¥¥……¥##R¥",//你的微信小程序的appsecret grant_type:"client_credential", env:"^%$#^@^" //你的微信小程序的环境参数};//创立 API 代理服务const apiServer = http.createServer((req, res) => { console.log("***************************************") console.log('[申请]来自='+req.url); if(req.url=="/"){ getAccessToken(res) }});//监听 API 端口apiServer.listen(apiPort, hostIp, () => { console.log('代理接口,运行于 http://' + hostIp + ':' + apiPort + '/');});function getAccessToken(res){ const url='https://api.weixin.qq.com/cgi-bin/token?appid='+data.appid+'&secret='+data.secret+'&grant_type='+data.grant_type; request({ url: url,//申请门路 method: "GET",//申请形式,默认为get headers: {//设置申请头 "content-type": "application/json", }, body: JSON.stringify(data)//post参数字符串}, function(error, response, body) { if (!error && response.statusCode === 200) { //编码类型 res.setHeader('Content-Type', 'text/plain;charset=UTF-8'); //容许跨域 res.setHeader('Access-Control-Allow-Origin', '*'); //返回代理内容 console.log("返回数据:"+body) res.end(body); } });}所有的第三方程序拜访微信后盾数据都须要这个token。appid和appsecret可在微信小程序公众服务平台里查看,env在微信开发者工具里查看。 ...

January 21, 2021 · 1 min · jiezi

关于node.js:nodejs中的文件系统

简介nodejs应用了异步IO来晋升服务端的解决效率。而IO中一个十分重要的方面就是文件IO。明天咱们会具体介绍一下nodejs中的文件系统和IO操作。 nodejs中的文件系统模块nodejs中有一个十分重要的模块叫做fs。这个模块提供了许多十分实用的函数来拜访文件系统并与文件系统进行交互。 简略统计一下,fs提供了上面这么多种应用的文件操作方法: fs.access(): 查看文件是否存在,以及 Node.js 是否有权限拜访。fs.appendFile(): 追加数据到文件。如果文件不存在,则创立文件。fs.chmod(): 更改文件(通过传入的文件名指定)的权限。相干办法:fs.lchmod()、fs.fchmod()。fs.chown(): 更改文件(通过传入的文件名指定)的所有者和群组。相干办法:fs.fchown()、fs.lchown()。fs.close(): 敞开文件描述符。fs.copyFile(): 拷贝文件。fs.createReadStream(): 创立可读的文件流。fs.createWriteStream(): 创立可写的文件流。fs.link(): 新建指向文件的硬链接。fs.mkdir(): 新建文件夹。fs.mkdtemp(): 创立长期目录。fs.open(): 设置文件模式。fs.readdir(): 读取目录的内容。fs.readFile(): 读取文件的内容。相干办法:fs.read()。fs.readlink(): 读取符号链接的值。fs.realpath(): 将绝对的文件门路指针(.、..)解析为残缺的门路。fs.rename(): 重命名文件或文件夹。fs.rmdir(): 删除文件夹。fs.stat(): 返回文件(通过传入的文件名指定)的状态。相干办法:fs.fstat()、fs.lstat()。fs.symlink(): 新建文件的符号链接。fs.truncate(): 将传递的文件名标识的文件截断为指定的长度。相干办法:fs.ftruncate()。fs.unlink(): 删除文件或符号链接。fs.unwatchFile(): 进行监督文件上的更改。fs.utimes(): 更改文件(通过传入的文件名指定)的工夫戳。相干办法:fs.futimes()。fs.watchFile(): 开始监督文件上的更改。相干办法:fs.watch()。fs.writeFile(): 将数据写入文件。相干办法:fs.write()。留神,下面fs提供的办法都是异步的,所谓异步的意思是,这些办法都提供了回调函数,不便异步触发相应的解决逻辑。咱们举一个简略的读取文件的例子: const fs = require('fs')fs.readFile('/tmp/flydean.txt', 'utf8' , (err, data) => { if (err) { console.error(err) return } console.log(data)})下面的例子中,咱们从/tmp文件中读取了一个flydean.txt文件。并在callback函数中别离对异样和失常的数据进行了解决。 fs在提供异步办法的同时,还提供了同步的办法调用,这个同步的办法就是在异步办法前面加上Sync: const fs = require('fs')try { const data = fs.readFileSync('/tmp/flydean.txt', 'utf8') console.log(data)} catch (err) { console.error(err)}看下将下面的办法改写成同步办法之后的样子。 两者的区别就是,同步办法会阻塞,始终等到file读取实现。 Promise版本的fs异步操作怎么能少得了Promsie, 因为fs中的操作都是异步的,如果大家不想通过callback来应用fs的话,fs也提供了Promise版本。 还是刚刚的readfile的例子,咱们看看如果应用Promise该怎么解决: ...

January 17, 2021 · 2 min · jiezi

关于node.js:深入理解nodejs中的异步编程

简介因为javascript默认状况下是单线程的,这意味着代码不能创立新的线程来并行执行。然而对于最开始在浏览器中运行的javascript来说,单线程的同步执行环境显然无奈满足页面点击,鼠标挪动这些响应用户的性能。于是浏览器实现了一组API,能够让javascript以回调的形式来异步响应页面的申请事件。 更进一步,nodejs引入了非阻塞的 I/O ,从而将异步的概念扩大到了文件拜访、网络调用等。 明天,咱们将会深刻的探讨一下各种异步编程的优缺点和发展趋势。 同步异步和阻塞非阻塞在探讨nodejs的异步编程之前,让咱们来探讨一个比拟容易混同的概念,那就是同步,异步,阻塞和非阻塞。 所谓阻塞和非阻塞是指过程或者线程在进行操作或者数据读写的时候,是否须要期待,在期待的过程中是否进行其余的操作。 如果须要期待,并且期待过程中线程或过程无奈进行其余操作,只能傻傻的期待,那么咱们就说这个操作是阻塞的。 反之,如果过程或者线程在进行操作或者数据读写的过程中,还能够进行其余的操作,那么咱们就说这个操作是非阻塞的。 同步和异步,是指拜访数据的形式,同步是指须要被动读取数据,这个读取过程可能是阻塞或者是非阻塞的。而异步是指并不需要被动去读取数据,是被动的告诉。 很显著,javascript中的回调是一个被动的告诉,咱们能够称之为异步调用。 javascript中的回调javascript中的回调是异步编程的一个十分典型的例子: document.getElementById('button').addEventListener('click', () => { console.log('button clicked!');})下面的代码中,咱们为button增加了一个click事件监听器,如果监听到了click事件,则会登程回调函数,输入相应的信息。 回调函数就是一个一般的函数,只不过它被作为参数传递给了addEventListener,并且只有事件触发的时候才会被调用。 上篇文章咱们讲到的setTimeout和setInterval实际上都是异步的回调函数。 回调函数的错误处理在nodejs中怎么解决回调的错误信息呢?nodejs采纳了一个十分奇妙的方法,在nodejs中,任何回调函数中的第一个参数为谬误对象,咱们能够通过判断这个谬误对象的存在与否,来进行相应的错误处理。 fs.readFile('/文件.json', (err, data) => { if (err !== null) { //处理错误 console.log(err) return } //没有谬误,则解决数据。 console.log(data)})回调天堂javascript的回调尽管十分的优良,它无效的解决了同步解决的问题。然而遗憾的是,如果咱们须要依赖回调函数的返回值来进行下一步的操作的时候,就会陷入这个回调天堂。 叫回调天堂有点夸大了,然而也是从一方面反映了回调函数所存在的问题。 fs.readFile('/a.json', (err, data) => { if (err !== null) { fs.readFile('/b.json',(err,data) =>{ //callback inside callback }) }})怎么解决呢? 别怕ES6引入了Promise,ES2017引入了Async/Await都能够解决这个问题。 ES6中的Promise什么是PromisePromise 是异步编程的一种解决方案,比传统的解决方案“回调函数和事件”更正当和更弱小。 所谓Promise,简略说就是一个容器,外面保留着某个将来才会完结的事件(通常是一个异步操作)的后果。 从语法上说,Promise 是一个对象,从它能够获取异步操作的音讯。 Promise的特点Promise有两个特点: 对象的状态不受外界影响。Promise对象代表一个异步操作,有三种状态:Pending(进行中)、Resolved(已实现,又称 Fulfilled)和Rejected(已失败)。 只有异步操作的后果,能够决定以后是哪一种状态,任何其余操作都无奈扭转这个状态。 一旦状态扭转,就不会再变,任何时候都能够失去这个后果。Promise对象的状态扭转,只有两种可能:从Pending变为Resolved和从Pending变为Rejected。 这与事件(Event)齐全不同,事件的特点是,如果你错过了它,再去监听,是得不到后果的。 Promise的长处Promise将异步操作以同步操作的流程表达出来,防止了层层嵌套的回调函数。 Promise对象提供对立的接口,使得管制异步操作更加容易。 ...

January 16, 2021 · 2 min · jiezi

关于node.js:npm源管理

原始源装置完node之后,默认的原始源是: https://registry.npmjs.org/cnpm原始源在国外,所以速度受到限制。 能够通过装置cnpm应用淘宝镜像来进行减速: // 装置cnpm命令,不会扭转npm的源npm install -g cnpm --registry=https://registry.npm.taobao.org//应用cnpm install然而应用cnpm有时会有一些奇怪的谬误,能够通过扭转源的形式来进行减速。 长期扭转源应用 npm 命令的时候,能够指定源: //本次从淘宝仓库源下载npm --registry=https://registry.npm.taobao.org install设置源间接设置源能够间接设置源,源能够是多个,但只有一个是失效的。 //设置淘宝源npm config set registry https://registry.npm.taobao.org//设置公司的源npm config set registry http://127.0.0.1:4873//查看源,能够看到设置过的所有的源npm config get registry也能够批改 ~/.npmrc ,增加源的设置: registry = https://registry.npm.taobao.org应用nrm治理源nrm 是一个 NPM 源管理器,能够应用 nrm 在不同的源切换。 装置nrmnpm install -g nrm列出可选的源nrm ls后果: * npm -------- https://registry.npmjs.org/ yarn ------- https://registry.yarnpkg.com/ cnpm ------- http://r.cnpmjs.org/ taobao ----- https://registry.npm.taobao.org/ nj --------- https://registry.nodejitsu.com/ npmMirror -- https://skimdb.npmjs.com/registry/ edunpm ----- http://registry.enpmjs.org/带* 的是以后应用的源。 切换源切换到taobao: nrm use taobao减少源能够减少定制的源,特地实用于增加企业外部的公有源。 ...

January 15, 2021 · 1 min · jiezi

关于node.js:CabloyJS自带工作流引擎的文档清单

文档清单CabloyJS自带工作流引擎文档曾经整理出来,欢送大家围观、拍砖 介绍 介绍演示:CMS审批工作流单元测试用例集流程定义 基本概念JSON标准listener标准listener标准-用户工作流程实例 外观Bean组件平安沙箱流程检索环境对象转移线 环境对象程序流流动节点 基本概念 环境对象开始事件 空开始事件定时开始事件原子起草开始事件完结事件 空完结事件流动 空流动服务流动用户工作流动用户工作 JSON标准外观Bean组件工作检索环境对象进阶篇(待续...)什么是CabloyJS自带工作流引擎家喻户晓,NodeJS作为后端开发语言和运行环境,样样都好,就差一个NodeJS工作流引擎。CabloyJS 4.0重点开发了NodeJS工作流引擎,并作为内置的根底外围模块,近一步拓展了NodeJS在后端的利用场景,为深刻研发各类商业业务逻辑,提供了根底撑持 NodeJS工作流引擎的特点更简便的配置:采纳JSON进行流程定义的配置,辞别XML配置文件的繁杂流程定义:反对历史版本、反对启用/禁用更清晰的架构:采纳三个外围模块用分层的机制实现工作流引擎的架构,让工作流不再神秘,源码也不再叠床架屋模块名称阐明a-flow流程定义、流程实例a-flownode流程节点(流动节点)a-flowtask流程工作反对业务流程和审批流程与原子数据生命周期联合,内置了一套基于原子数据的审批工作流。参见:原子阶段(数据生命周期)与表单验证联合,反对别离配置不同流程节点的读取字段权限和批改字段权限。参见:表单验证可通过AOP机制定制工作流逻辑。参见:AOP可通过Listener机制定制工作流逻辑。参见:listener标准开放式的架构,反对更多流程节点的定制开发蕴含大量测试驱动代码,可疾速上手应用工作流与Activiti的比照流程定义是工作流引擎的灵魂,一个正当的流程定义标准,既要思考应用的便利性,又要思考性能个性的可扩展性 Activiti无疑是Java语言畛域工作流引擎的标杆,根据BPMN2.0标准采纳XML格局来定义工作流 1. JAVA + BPMN + XMLBPMN + XML的长处是规范对立,与JAVA语言的开发调性相匹配。当然,毛病是繁琐,如果脱离了图形化编辑工具,采纳手写XML定义,十分不便当 2. JS + 类BPMN + JSONCabloyJS通过重复的评估与衡量,决定依然参考BPMN标准的个性集,然而采纳JSON格局进行定义。尽管属于自定义格局,但合乎JS语言的调性,长处是简洁、易写、易读,同样具备优良的可迁移性 相干链接官网: https://cabloy.com/GitHub: https://github.com/zhennann/cabloy

January 15, 2021 · 1 min · jiezi

关于node.js:nodejs事件和事件循环详解

简介上篇文章咱们简略的介绍了nodejs中的事件event和事件循环event loop。本文本文将会更进一步,持续解说nodejs中的event,并探讨一下setTimeout,setImmediate和process.nextTick的区别。 nodejs中的事件循环尽管nodejs是单线程的,然而nodejs能够将操作委托给零碎内核,零碎内核在后盾解决这些工作,当工作实现之后,告诉nodejs,从而触发nodejs中的callback办法。 这些callback会被退出轮循队列中,最终被执行。 通过这样的event loop设计,nodejs最终能够实现非阻塞的IO。 nodejs中的event loop被分成了一个个的phase,下图列出了各个phase的执行程序: 每个phase都会保护一个callback queue,这是一个FIFO的队列。 当进入一个phase之后,首先会去执行该phase的工作,而后去执行属于该phase的callback工作。 当这个callback队列中的工作全副都被执行结束或达到了最大的callback执行次数之后,就会进入下一个phase。 留神, windows和linux的具体实现有稍许不同,这里咱们只关注最重要的几个phase。问题:phase的执行过程中,为什么要限度最大的callback执行次数呢? 答复:在极其状况下,某个phase可能会须要执行大量的callback,如果执行这些callback破费了太多的工夫,那么将会阻塞nodejs的运行,所以咱们设置callback执行的次数限度,以防止nodejs的长时间block。 phase详解下面的图中,咱们列出了6个phase,接下来咱们将会一一的进行解释。 timerstimers的中文意思是定时器,也就是说在给定的工夫或者工夫距离去执行某个callback函数。 通常的timers函数有这样两种:setTimeout和setInterval。 一般来说这些callback函数会在到期之后尽可能的执行,然而会受到其余callback执行的影响。 咱们来看一个例子: const fs = require('fs');function someAsyncOperation(callback) { // Assume this takes 95ms to complete fs.readFile('/path/to/file', callback);}const timeoutScheduled = Date.now();setTimeout(() => { const delay = Date.now() - timeoutScheduled; console.log(`${delay}ms have passed since I was scheduled`);}, 100);// do someAsyncOperation which takes 95 ms to completesomeAsyncOperation(() => { const startCallback = Date.now(); // do something that will take 10ms... while (Date.now() - startCallback < 10) { // do nothing }});下面的例子中,咱们调用了someAsyncOperation,这个函数首先回去执行readFile办法,假如这个办法耗时95ms。接着执行readFile的callback函数,这个callback会执行10ms。最初才回去执行setTimeout中的callback。 ...

January 14, 2021 · 2 min · jiezi

关于node.js:你不知道的node安装方法

在开发的过程中,咱们常常会须要装置 node环境,在装置多边 node环境之后,我本人总结了一下,才发现装置 node原来环境原来能够这么简略,心愿对你有所帮忙。1.废话不多说,间接上操作 倡议抉择稳定版,点击 其余下载 滚动到最上面,点击 所有下载选项 依据本人电脑进行抉择下载实现之后,会失去有一个压缩包,进行解压,你会看到这样的成果 把这个解压文件,拷贝到你想要装置的地位,而后配置一下环境。2.做完下面的操作之后,须要执行如下命令: npm config set prefix "D:\SDE\node-v14.15.4-win-x64\node_global"npm config set cache "D:\SDE\node-v14.15.4-win-x64\node_cache"留神:D:SDEnode-v14.15.4-win-x64是我的项目目录,依据本人的状况,本人批改。3.增加到环境变量 把D:\SDE\node-v14.15.4-win-x64\node_global 增加到全局环境变量如果还不晓得如何增加环境变量,在这里一个解说,找到电脑,右击属性>高级零碎设置>环境变量,找到零碎变量(点击编辑,而后点击新增,把 D:SDEnode-v14.15.4-win-x64node_global 复制进去,保留就能够了)4.本期的分享到了这里就完结啦,是不是很nice,心愿对你有所帮忙,让咱们一起致力走向巅峰。

January 13, 2021 · 1 min · jiezi

关于node.js:node中使用shell脚本

背景在开发中咱们在特定的场合下可能须要一些脚本来批量解决咱们的业务逻辑,在nodejs如何调用shell脚本呢? 新建我的项目下新建脚本文件 touch newFile.sh批改文件权限 chmod 777 newFile.sh 批改文件为可读可写可执行nodejs调用文件读取//应用nodejs的子过程外面的文件读取办法const { execFile } = require('child_process'); 示例DocsService.publishAllDocs = (req, res) => { req.session.touch(); const { docName, pathName, saveDocsList, docType } = req.body; var docText = req.body.docText; var newGit = req.body.newGit; //获取文件门路 var filepath = path.join(__dirname, '../../bin/rnsource/publishAllDocs.sh'); var fileArr, fileName, spath, dirnameBack, docbackList = [], docbackPath, docPath = ""; var username = req.session.user_name; var str = docName+'/'+ pathName + '|'+ username; var reg = new RegExp(`^(${str})`); saveDocsList.map((item, index)=>{ fileArr = item.pathName.split("/"); fileName = fileArr[fileArr.length-1]; if(docType == "docsify"){ dirnameBack = fileName != "" ? `../../gitlib/docBackup/${docName}/docs/${item.pathName}`:`../../gitlib/docBackup/${docName}/docs/README.md` }else{ spath = item.pathName.split(fileName)[0]; dirnameBack = spath != "" ?'../../gitlib/docBackup/'+ docName+'/'+ spath +'/'+fileName:'../../gitlib/docBackup/'+ docName+'/' + fileName; } docbackPath = path.join(__dirname, dirnameBack); docbackList.push(docbackPath); docPath += docbackPath + " "; }) docPath += "" //cwd设置以后门路 我这边设置的就是nodejs代码js以后的地位 execFile(filepath, [docName, docPath, docType], { cwd: '.' }, function(err, stdout, stderr){ logger.info(stdout); if(err){ loggerFileError({user:username,docName:docName,pathName:'all',operate:"gitbook文件一键公布",err}); res.json({ respCode: -1, errMsg: "一键公布失败" }) }else{ res.json({ respCode: 0, msg: "一键公布胜利" }) gitPush({ docName, fileName, docbackPath: docbackList, username, pathName, docType }) unblockFile({ docName, username, pathName, reg }); } }) }回调执行胜利会返回脚本执行的命令 ...

January 6, 2021 · 2 min · jiezi

关于node.js:基于原生JS实现的Bean容器和AOP编程

Bean是什么咱们晓得Bean是Spring最根底的外围构件,大多数逻辑代码都通过Bean进行治理。NestJS基于TypeScript和依赖注入也实现了相似于Spring Bean的机制:服务提供者(Provider) CabloyJS则是在原生JS(Vanilla JS)上实现了更轻量、更灵便的Bean容器 理念CabloyJS在设计Bean容器机制时,遵循了以下3个理念: 1. 简直所有事物都是Bean咱们绝大多数逻辑代码都通过Bean组件进行治理,比方:Controller、Service、Model、Middleware、Event、Queue、Broadcast、Schedule、Startup、Flow、Flow Task,等等 CabloyJS 4.0在实现了Bean容器之后,基本上所有外围组件都以Bean为根底进行了重构。比方基于EggJS的Controller、Service、Middleware,也实现了Bean组件化2. Bean反对AOP所有Bean组件都能够通过AOP组件进行逻辑扩大 3. AOP也是一种BeanAOP组件既然也是Bean,那么也能够通过其余AOP组件进行逻辑扩大 这种递归设计,为零碎的可定制性和延展性,提供了弱小的设想空间定义BeanCabloyJS约定了两种定义Bean的模式:app和ctx。因为Bean被容器托管,能够很不便的跨模块调用。因而,为了清晰的辨识Bean被利用的场景,个别约定:如果Bean只被本模块外部调用,那么就应用app模式;如果大概率会被其余模块调用,那么就应用ctx模式 1. app模式比方:Controller、Service都采纳app模式 src/module/test-party/backend/src/bean/test.app.js module.exports = app => { class appBean extends app.meta.BeanBase { actionSync({ a, b }) { return a + b; } async actionAsync({ a, b }) { return Promise.resolve(a + b); } } return appBean;};2. ctx模式比方:ctx.bean.atom、ctx.bean.user、ctx.bean.role都采纳ctx模式 src/module/test-party/backend/src/bean/test.ctx.js module.exports = ctx => { class ctxBean { constructor(moduleName) { this._name = moduleName || ctx.module.info.relativeName; } get name() { return this._name; } set name(value) { this._name = value; } actionSync({ a, b }) { return a + b; } async actionAsync({ a, b }) { return Promise.resolve(a + b); } } return ctxBean;};ctx.module.info.relativeName: 因为ctx模式的Bean常常被其余模块调用,那么能够通过此属性获得调用方模块的名称注册Bean对于大多数组件,EggJS采纳约定优先的策略,会在指定的地位查找资源,并主动加载。而CabloyJS采纳显式注册,从而Webpack能够收集所有后端源码,实现模块编译的个性 ...

January 6, 2021 · 2 min · jiezi

关于node.js:Pride深入解析-NodeJS-的微任务运行规则

前言本文探讨的外围基本概念是 Event Loop,即事件循环,是 JavaScript 的执行模型,这是实现异步编程的外围。在不同的平台有不同的实现,浏览器基于 HTML5 的标准各自实现,而 NodeJS 基于 libuv 外围。他们尽管都是实现了异步告诉的成果,但运行规定还是有些差异。网络上对于“事件循环”的文章有很多,本文就不再多赘述,请浏览本文 前准备好这些背景常识,重点是 NodeJS 运行的 6 个阶段以及宏工作队列(Macrotask Queue)和微工作队列(Microtask Queue)的基本概念。自己能力无限,不足之处还请批评指教。 本文要解决的问题在 NodeJS 中运行齐全局同步代码后是先运行微工作,还是先运行宏工作?不同版本的 NodeJS 运行微工作的机会有差别吗?Next Tick Queue 和 Other Micro Queue 都是 NodeJS 中的微工作队列,他们的运行机会有什么差异?微队列是一次清空,还是每一轮循环运行一个工作?举个例子console.log("start")setTimeout(() => { console.log(1) Promise.resolve().then(() => { console.log(2) }) setTimeout(() => { console.log(3) }) setImmediate(() => { console.log(4) }) process.nextTick(() => { console.log(5) })})setTimeout(() => { console.log(6) Promise.resolve().then(() => { console.log(7) }) setTimeout(() => { console.log(8) }) setImmediate(() => { console.log(9) }) process.nextTick(() => { console.log(10) })})process.nextTick(() => { console.log(11)})console.log("end")阐明下面的例子根本能够解决上述的疑难,每一个回调函数都只会打印出一个数字,这个数字也相当于该函数的编号;全局的“start”和“end”表明了全局同步代码的运行开始与完结。 ...

January 5, 2021 · 2 min · jiezi

关于node.js:在飞书上开发第一个小程序HelloWorld

原创首发于飞书文档由此拜访: 2020年最初一天的几个小时,点上一根香,泡好茶,带上降噪耳机在音乐的陪伴下写写代码。2020年第一天,没搞完的持续搞,加油~开发环境的搭建1、零碎是MacOS,装置Node.js,装置的同时也会装置好npm 下载地址 常用命令如下: # 查看Node.js版本node -v# 查看npm版本npm -v# 查看node装置目录which node# 更新已装置的npm库npm update -g# 全局装置n命令,用n命令降级Node.jsnpm install -g n# 降级到最新稳定版n stable# 降级到最新版n latest# 降级到指定版n v14.15.3# 切换应用版本n 14.15.3 (ENTER) 2、装置命令行工具 curl -L https://sf1-scmcdn-tos.pstatp.com/obj/larkdeveloper/opdev/scripts/install_1.7.0.sh | sh 3、装置实现后,执行以下命令校验是否装置胜利 # 是否装置胜利opdev help# 查看装置的版本opdev --version# 查看单个命令帮忙信息,如上传命令opdev upload --help 4、上传、预等操作须要先登录飞书账号,输出以下命令会关上默认浏览器进行登录。 这个中央比拟坑,不晓得是工具兼容的问题还是什么,尝试屡次失败后敞开终端从新关上才ok。 # 登录opdev login# 抉择要登录的环境,在这里咱们抉择“Feishu”5、登陆胜利,返回终端,显示以下信息,阐明登录胜利。 创立第一个小程序1、进入飞书开发者后盾,创立一个企业自建利用2、在企业自建利用列表中点击方才创立的HelloWorld利用进入利用详情页 3、在利用详情页中,点击左侧“凭证与根底信息”标签,查看右侧“利用凭证”下的App ID(App ID 是利用的惟一标识)并复制。 4、从内置模板中生成一个“HelloWord”的小程序Demo # 查看内置模版列表opdev template# 返回后果,自带5个Demo# Available templates:# - hello-world Gadget base template# - gadget-demo Gadget api/component demo# - widget-demo-approve Widget demo for Approve app# - widget-demo-report Widget Demo for Report app# - block-demo Block base template# 用内置模版创立小程序Demo, [project-path]为Demo目录opdev new [project-path] -t hello-world 5、编辑“project.config.json”中的第9行,将方才复制的App ID填入,保留退出。 ...

January 1, 2021 · 1 min · jiezi

关于node.js:看起来很唬人然而却简单实用的CAP理论

在做分布式系统开发时,常常会或多或少的听到CAP实践、或者是解决节点间数据一致性的问题。CAP实践很简略,但却是很多软件设计的宏观指导,因而也有人将之称为架构师必须把握的实践之一。鉴于实践的货色相对来说比拟形象而且繁琐,因而咱们先举个例子:有一天你打王者光荣连跪,于是找了一个大神鲁班,带你腾飞: 于是就产生了下边的对话(1)射手鲁班:救救我,谢谢 辅助蔡文姬:收到(2)辅助蔡文姬:我来抓人了 射手鲁班:收到 如果所有良好,那么所有都OK 然而假若这时候YY语音忽然挂掉了(1)射手鲁班:救救我,谢谢 蔡文姬,没有响应 (2)辅助蔡文姬:我来抓人了 射手鲁班,没有响应 那么接下来有两种策略:1、 临时先不论YY语音的问题,持续打好游戏。2、先不打游戏了,切屏打电话给对方,看下是不是产生了什么情况 是的,这波及到所谓的CAP实践了,也就是在分布式场景下,如果不同节点之间的通信呈现了问题,那么不同节点的响应策略应该是什么样的。是该暂停响应,期待连贯复原,还是应该保持响应,疏忽数据的不一致性。咱们先来看下计算机领域中,CAP的业余解释:一致性 Consistency:在分布式系统中,所有的数据备份,在任意时刻都要求统一;可用性 Availability:对于分布式系统中的节点,在任意时候都能够失常的进行读写响应,并且不超时;分区容错性 Partition tolerance:当节点之间的通信呈现(防盗连贯:本文首发自http://www.cnblogs.com/jilodr... )故障时,整个分布式系统依然能够运行起来,不至于间接解体掉;P是背景,也就是在分布式系统下,如果节点之间的通信呈现了问题,那么整个零碎依然在运行,期待网络复原后,整个零碎依然能够失常操作。 通过实践以及理论的推演,咱们发现在P的背景下,AC不能够共存。也就是你无奈做到既保证了节点的可用性,还保障了一致性。业余的推演证实,这里就不说了,笔者本人的了解是这样的:当节点之间的网络解体时,节点如果想要可能反对可用性,势必会造成数据的批改,从而造成数据的不统一,而网络又解体掉,因而没有方法进行节点间的数据同步。当初对于接下来的解决策略有两个抉择:(1)如果节点想要反对一致性呢,那么惟一的抉择就是不能进行数据的写,这是因为节点之间无奈进行数据的同步,因而只能放弃写操作,这就导致失去了高可用性。(2)如果反对了写,那么就会呈现节点间的数据不统一,并且因为网络问题,无奈及时同步,这就失去了高始终性。 这套实践有什么用呢?他能够明确指出,对于分布式系统来说,无奈做出数据完满始终,而且有高可用的场景。架构设计必须要做出取舍。1、听从可用性,放弃高一致性2、反对高始终性,放弃高可用性具体应该如何抉择,由业务来决定。如果你的零碎反对短暂的业务进展,然而零碎不能出错,那么就要偏向于CP计划,如实时通话零碎,财务交易系统。如果你的零碎反对临时的数据不一致性,然而肯定要保障高可用性,如直播点赞,评论。那么就要偏向于AP计划。无所谓哪种计划更优良,而是须要由业务来驱动技术的选型。很多人说,不是CAP,三者取其二么?为什么你这里只有CP,和AP?这两种了解其实都能够,然而(留神,要画重点了)P所代表的是分区容忍性,是指分布式场景下,对于网络通信问题下依然可用,这个是前提。CP和AP是基于这个前提探讨的两种计划。如果划掉P,取AC,也就是单机场景下的一致性和可用性(防盗连贯:本文首发自http://www.cnblogs.com/jilodr... )问题,这就失去了探讨的意义。这好比在中学物理中R=U/I ,电阻等于电压除以电流。然而你不能了解为电阻与电压成正比,与电流成反比,因为电阻只与资料和规格相干。你能够依照公式推算出数据,然而不代表是字面的含意。 另外须要留神的是,上述情况下,都是实践模型,其中疏忽了数据一致性所须要的网络提早。也就是说,在理论状况中,因为网络的延时问题,高效的CP零碎十分难实现。同时又因为互联网产品中自身须要的疾速响应,所以在理论的开发中,往往AP模式的设计,相对来说占比会更大一点。那么如何躲避掉一致性的影响呢?这里提供两个思路1、 数据的最终一致性,呈现一致性问题没关系,只有不影响到外围的数据计算,是能够承受的。只有最终的数据可能保障一致性,满足幂等性即可。2、 缩短数据一致性复原的工夫,也就是如果呈现数据不统一的问题,零碎能够想方法缩短复原数据的耗时,如果当申请再次进来时,如果数据曾经复原实现,那么对于外界来说,就不会感知到此次的不统一。

December 30, 2020 · 1 min · jiezi

关于node.js:你知道-Mybatis-框架如何实现级联关系吗

级联关系实现的形式一对一一对多案例实操一对一关系实现形式 resultType/resultMap 接口办法 /** 一对一关联查问 resultType @param userId @return*/ UserDto queryUserCardInfoForResultType(@Param("userId")int userId); sql 查问 <select id="queryUserCardInfoForResultType" resultType="userDto"> SELECT u.id, u.user_name AS userName, u.user_pwd AS userPwd, u.flag, u.cid, c.number FROM USER u LEFT JOIN card c ON u.cid = c.id WHERE u.id = #{userId} </select> resultType 实现<select id="queryUserByIdResultType" parameterType="int" resultType="com.xxx.dto.UserDto"> SELECT u.id, u.user_name AS userName, u.create_time, u.flag, u.cid AS cid, c.number FROM User u LEFT JOIN card c u ON u.cid =c.id WHERE u.id = #{id} </select> ...

December 30, 2020 · 2 min · jiezi

关于node.js:node-fs模块练习-模拟小程序开发工具快速生成page中文件夹含wxmlwxssjsonjs文件

知识点: node 命令行传参、fs 模块办法~~~~ 第一步 小程序根目录,新建 genWxPages.js文件let dirname = process.argv.splice(2)[0];const fs = require('fs')const path = require('path')class GennerateWXPage { /** * * @param {string} dirname 生成page名 * @param {string} sourcePath 生成文件绝对路径,默认以后文件所在门路 */ genDir(dirname, sourcePath = path.resolve('./')) { // 检测page文件夹是否存在 if (!fs.existsSync(`${sourcePath}/pages`)) { fs.mkdirSync(`${sourcePath}/pages`) } if (!fs.existsSync(`${sourcePath}/pages/${dirname}`)) { fs.mkdirSync(`${sourcePath}/pages/${dirname}`) } this.genWXML(dirname, sourcePath) this.genJSON(dirname, sourcePath) this.genJS(dirname, sourcePath) this.genWXSS(dirname, sourcePath) // 判断文件是存在 } genWXML(dirname, sourcePath) { if (!fs.existsSync(`${sourcePath}/pages/${dirname}/${dirname}.wxml`)) { let wxml_content = `<!--pages/${dirname}.wxml--><text>pages/${dirname}.wxml</text> ` fs.writeFileSync(`${sourcePath}/pages/${dirname}/${dirname}.wxml`, wxml_content) } } genJSON(dirname, sourcePath) { if (!fs.existsSync(`${sourcePath}/pages/${dirname}/${dirname}.json`)) { let json_content = `{ "usingComponents": {}} ` fs.writeFileSync(`${sourcePath}/pages/${dirname}/${dirname}.json`, json_content) } } genJS(dirname, sourcePath) { if (!fs.existsSync(`${sourcePath}/pages/${dirname}/${dirname}.js`)) { let js_content = `// pages/${dirname}.jsPage({ /** * 页面的初始数据 */ data: { }, /** * 生命周期函数--监听页面加载 */ onLoad: function (options) { }, /** * 生命周期函数--监听页面首次渲染实现 */ onReady: function () { }, /** * 生命周期函数--监听页面显示 */ onShow: function () { }, /** * 生命周期函数--监听页面暗藏 */ onHide: function () { }, /** * 生命周期函数--监听页面卸载 */ onUnload: function () { }, /** * 页面相干事件处理函数--监听用户下拉动作 */ onPullDownRefresh: function () { }, /** * 页面上拉触底事件的处理函数 */ onReachBottom: function () { }, /** * 用户点击右上角分享 */ onShareAppMessage: function () { }}) ` fs.writeFileSync(`${sourcePath}/pages/${dirname}/${dirname}.js`, js_content) } } genWXSS(dirname, sourcePath) { if (!fs.existsSync(`${sourcePath}/pages/${dirname}/${dirname}.wxss`)) { let wxss_content = `/* pages/${dirname}.wxss */ ` fs.writeFileSync(`${sourcePath}/pages/${dirname}/${dirname}.wxss`, wxss_content) } }}if(dirname) { let gen = new GennerateWXPage() gen.genDir(dirname)} else { // ....}第二步 执行命令 node genWxPages.js goods-listgood-list 为文件名 ...

December 29, 2020 · 2 min · jiezi

关于node.js:typescript编写的node应用部署在docker中遇到的问题

问题无奈应用pm2,因为pm2会后盾运行,docker作为容器时,如果无前台运行的过程,将敞开容器。无奈应用pm2-runtime,因为pm2-runtime尚不反对ts-node。解决方案计划1:应用 ts-node 跳过pm2间接运行我的项目计划2:应用 tsc 把ts编译为js,再应用pm2运行我的项目计划3:从新编译pm2-runtime,减少其反对ts的能力 计划1的做法,是比拟可取的,因为咱们应用docker作为容器,其自身就具备主动重启等特点,所以再减少pm2对过程进行爱护是多余的,且存在性能损耗。 计划2须要改变我的项目的配置,在测试环境和本地开发环境不应用docker,则须要做兼容,改变较大,且因为计划1的存在,该计划性价比较低。 计划3,性价比更低。

December 28, 2020 · 1 min · jiezi

关于node.js:NodejsVuejs使用jsSHA库进行SHA123加密

1 概述jsSHA是一个用JS+TS实现残缺SHA系列加密算法的加密库,包含: SHA1SHA-224/256/384/512SHA3-224/256/384/512SHAKE128/256cSHAKE128/256KMAC128/256官网Github戳这里,目前已有2k的star,这里是一些应用加密算法的例子。 2 装置并引入装置应用npm或cnpm: npm install --save jssha# 或cnpm install --save jssha引入时,依据package.json中的type进行相应引入: const jsSHA = require("jssha") //commonjsimport jsSHA from "jssha" //module若为 "type":"commonjs"则应用 const jsSHA = require("jssha")3 哈希一个简略的例子如下: const jsSHA = require("jssha")const shaObj = new jsSHA("SHA-512","TEXT",{encoding:"UTF8"})shaObj.update("test")console.log(shaObj.getHash("HEX"))首先申明了一个shaObj,通过update传递明文,并通过getHash("HEX")即失去哈希值,另外update能够调用屡次,最初应用getHash即可。 jsSHA()有三个参数:哈希算法、输出格局以及参数设置(可选)。 3.1 哈希算法第一个参数是哈希算法,反对的算法如下: SHA-1SHA-224SHA-256SHA-384SHA-512SHA3-224SHA3-256SHA3-384SHA3-512SHAKE128SHAKE256目前不倡议应用SHA-1,倡议应用SHA-2(SHA-224、256/384/512)或SHA-3(SHA3-224/256/384/512)。 而SHAKE是Secure Hash Algorithm and KECCAK的缩写,在FISP 202规范中定义,与SHA-3相似,然而输入是有限位数的。因而定义的时候须要指定输入的位数,不然的话会失去如下报错: 在getHash中加上参数即可: const jsSHA = require("jssha")const shaObj = new jsSHA("SHAKE128","TEXT",{encoding:"UTF8"})shaObj.update("test")console.log(shaObj.getHash("HEX",{outputLen:1024}))3.2 输出格局输出格局的取值如下: HEXTEXTB64BYTESARRAYBUFFERUNIT8ARRAY3.3 参数选项个别罕用两个: encoding:编码,容许取值UTF8/UTF16BE/UTF16LEnumRounds:哈希轮数其余的参数能够查看源码。 3.4 getHashgetHash是获取哈希后果的函数,第一个参数能够是: HEXB64BYTESUINT8ARRAYARRAYBUFFER与下面的输出格局对应,能够带上输入长度选项,对于HEX能够带上outputUpper示意是否大写: 4 HMACHMAC是一种基于哈希函数和密钥进行音讯认证的办法,应用时须要指定密钥: ...

December 28, 2020 · 1 min · jiezi

关于node.js:如何用Eggjs从零开始开发一个项目3

上一篇中咱们编写了用户注册登录、登录的代码,学习了如何进行用户的认证(JWT),如何平安地存储用的明码(hash)。这一篇咱们有以下2个工作: 获取token中的数据;通过model来同步数据库。获取token中的数据用户登录的时候咱们曾经用户的一些根本信息加密存储到token中,通过路由配置咱们能简略的去管制哪些接口须要登录,哪些接口不须要登录,然而如果再细化到用户或者用户角色,只是从路由层面就难以管制了,咱们须要拿到用户信息,并将用户信息存储在session中,不便咱们随时取用。那要怎么做呢?这里咱们须要编写一个中间件来实现这个性能。代码如下: // app/middleware/eggJwtmodule.exports = options => { return async function jwt(ctx, next) { const token = ctx.request.header.authorization; if (token) { // 这里有个坑,前端个别传过来是Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYW1lIjoieGl... // 然而解码时不须要Bearer,所以须要手动解决一下 const tokenStr = token.split(' ')[1]; try { // 解码token并存储到session中 const decode = ctx.app.jwt.verify(tokenStr, options.secret); ctx.session.user = decode; await next(); } catch (error) { ctx.status = 500; ctx.body = { message: error.message }; return; } } else { ctx.status = 401; ctx.body = { message: '用户未登录' }; return; } };};这里阐明一下eggjs的插件机制,如果你在config.default.js中配置: ...

December 27, 2020 · 2 min · jiezi

关于node.js:nodejs篇进程与集群cluster

咱们启动一个服务、运行一个实例,就是开一个服务过程,Node.js 里通过 node app.js 开启一个服务过程,多过程就是过程的复制(fork),fork 进去的每个过程都领有本人的独立空间地址、数据栈,一个过程无法访问另外一个过程里定义的变量、数据结构,只有建设了 IPC 通信,过程之间才可数据共享。child_processnode.js中能够通过上面四种形式创立子过程: child_process.spawn(command, args)child_process.exec(command, options)child_process.execFile(file, args[, callback])child_process.fork(modulePath, args)spawnconst {spawn} = require("child_process");// 创立 文件spawn("touch",["index.js"]);spawn()会返回child-process子过程实例: const {spawn} = require("child_process");// cwd 指定子过程的工作目录,默认当前目录const child = spawn("ls",["-l"],{cwd:__dirname});// 输入过程信息child.stdout.pipe(process.stdout);console.log(process.pid,child.pid);子过程同样基于事件机制(EventEmitter API),提供了一些事件: exit:子过程退出时触发,能够得悉过程退出状态(code和signal)disconnect:父过程调用child.disconnect()时触发error:子过程创立失败,或被kill时触发close:子过程的stdio流(规范输入输出流)敞开时触发message:子过程通过process.send()发送音讯时触发,父子过程音讯通信close与exit的区别次要体现在多过程共享同一stdio流的场景,某个过程退出了并不意味着stdio流被敞开了子过程具备可读流的个性,利用可读流实现find . -type f | wc -l,递归统计当前目录文件数量: const { spawn } = require('child_process');const find = spawn('find', ['.', '-type', 'f']);const wc = spawn('wc', ['-l']);find.stdout.pipe(wc.stdin);wc.stdout.on('data', (data) => { console.log(`Number of files ${data}`);});execspawn()跟exec()办法的区别在于,exec()不是基于stream的,exec()会将传入命令的执行后果暂存到buffer中,再整个传递给回调函数。 spawn()默认不会创立shell去执行命令(性能上会稍好),而exec()办法执行是会先创立shell,所以能够在exec()办法中传入任意shell脚本。 const {exec} = require("child_process");exec("node -v",(error,stdout,stderr)=>{ if (error) console.log(error); console.log(stdout)})exec()办法因为能够传入任意shell脚本所以存在平安危险。spawn()办法默认不会创立shell去执行传入的命令(所以性能上略微好一点),不过能够通过参数实现: ...

December 24, 2020 · 4 min · jiezi

关于node.js:NODE-Promise

在应用node开发中,通过会使用async和await,这样能够不便将异步执行的程序,书写为人更容易了解的过程执行。 不过,有时候,一些异步程序并不存在因果依赖关系,因此能够通过Promise.all 并行执行,从而进步执行速度。 [aretuls,b_result]= Promise.all([a,b])

December 24, 2020 · 1 min · jiezi

关于node.js:前端脚手架CLI生成模版命令工具包括npm包的发布脚手架的搭建注意事项优化等

NodeJs的呈现,让前端工程化的理念不断深入,正在向正规军凑近。先是带来了Gulp、Webpack等弱小的构建工具,随后又呈现了vue-cli和create-react-app等欠缺的脚手架,提供了残缺的我的项目架构,让咱们能够更多的关注业务,而不用在我的项目基础设施上破费大量工夫。 平时咱们都只专一在业务上的开发,拿起一套开箱即用的模板我的项目就间接干。然而,这些现成的脚手架未必就能满足咱们的业务需要,也未必是最佳实际,这时咱们就能够本人开发一个脚手架,那么咱们应用的脚手架外面到底做了什么,如何本人搭建脚手架呢? 脚手架代码github地址:https://github.com/hourong88/... 以下为注释,文章构造: 发问1.脚手架须要实现什么? 初始化我的项目模版能力。 2.脚手架须要什么性能? 问询性能下载模版(模版与脚手架拆散,互不影响)写入模版优化(git初始化,装置依赖等)3.用什么工具实现? commander.js 命令行工具chalk 命令行输入款式丑化Inquirer.js 命令行交互当然还有,download-git-repo git仓库代码下载,ora 命令行加载中成果等优化依赖工具,都能够在此基础上,进行丰盛。 以下分为两步实现: 本地创立cli脚手架并测试 ;公布脚手架咱们失常的流程是创立本地脚手架,绑定git仓库,公布包,从易到难,咱们反过来,本文先讲怎么发一个最简略的npm包,而后把脚手架搭好了,走一遍发包流程,就OK了。 一、公布npm包本地创立我的项目首先,咱们须要创立一个我的项目,这里就叫portal-cli, 我的项目构造如下: - commands  // 此文件夹用于搁置自定义命令- utils- index.js  // 我的项目入口- readme.md为了测试,咱们先在index.js放点内容: #!/usr/bin/env node// 必须在文件头增加如上内容指定运行环境为nodeconsole.log('hello cli');对于个别的nodejs我的项目,咱们间接应用node index.js就能够了,然而这里是脚手架,必定不能这样。咱们须要把我的项目公布到npm,用户进行全局装置,而后就能够间接应用咱们自定义的命令,相似portal-cli这样。 所以,咱们须要将咱们的我的项目做下改变,首先在package.json中增加如下内容: "bin": {    "portal-cli": "index.js"  },这样就能够将portal-cli定义为一个命令了,但此时仅仅只能在我的项目中应用,还不能作为全局命令应用,这里咱们须要应用npm link将其链接到全局命令,执行胜利后在你的全局node_modules目录下能够找到相应文件。而后输出命令测试一下,如果呈现如下内容阐明第一步曾经胜利一大半了: anna@annadeMacBook-Air job % > portal-clihello cli*如果全局有bin雷同名字的,会报错,须要把package.json外面bin起的名字批改一下 公布npm包注意事项:npm官网注册一个npm账户,已有账户的能够跳过这一步应用npm login登录,须要输出username、password、emailnpm whoami 查看本人是否胜利登陆npm link本地调试,下面曾经调试的,跳过这一步应用npm publish公布每次公布npm包,都要批改版本号//npm publish报错npm notice integrity:     sha512-Jkfy0M/VyAkQb[...]B9Ifdw2hF2CGQ==npm notice total files:   7                                       npm notice npm ERR! code E403npm ERR! 403 403 Forbidden - PUT http://registry.npmjs.org/portal-portal-cli-hourong - Forbiddennpm ERR! 403 In most cases, you or one of your dependencies are requestingnpm ERR! 403 a package version that is forbidden by your security policy.我公布包的时候,调整了几次,报错,不是403就是404,那个捉急。上面总结了几个报错查看清单: 查看npm包的名字跟已有的包名是否反复,要么就改个名字,或者加后缀如果用的是cnpm源,要改成npm,办法见上面阐明registry如果还是报403,你的账号看是不是刚刚注册的,如果是的话,须要进入你的邮箱,验证一下邮箱。版本号是否更新如果以上3步批改了,还是报403谬误,就连贯手机4g热点再公布一下。个别公布不了,依照以上5点进行查看,能够解决。 查看第2步npm源的办法 查看本地以后应用的源 registry npm config get registry 切换源 registry npm config set registry <http://registry.npmjs.org/> 长期切换 registry npm publish --registry <http://registry.npmjs.org/> 设置完当前,再次查看以后源是否是http://registry.npmjs.org 留神:国内目前公布组件时,必须切换为npmjs,否则npm publish也不会胜利 科普npm registry 简略来说,npm registry就相当于一个包注册管理中心。它治理着全世界的开发者们公布上来的各种插件,同时开发者们能够通过npm install的形式装置所须要的插件。 npm官网registry为:http://registry.npmjs.org/ 国内速度较快的为:https://registry.npm.taobao.org/ 以上波及到的要害命令: ...

December 23, 2020 · 1 min · jiezi

关于node.js:CabloyJS-v400支持工作流引擎及更多-????

截至2020年12月21日冬至,花了近5年工夫作出最小可用NodeJS开源全栈框架,这就是CabloyJS V4.0.0 5年,90个模块,30万行代码,5400次提交(Commits),开启NodeJS全栈开发的全新体验 CabloyJS V4.0.0次要实现了以下个性采纳lerna将cabloy所有外围模块集中在一个源码仓库治理基于原生JS的Bean容器和AOP架构 简直所有事物都是BeanBean反对AOPAOP也是一种Bean通用的NodeJS工作流引擎原子三生三世(数据的生命周期治理):草稿->归档->历史基于NodeJS工作流引擎的草稿审核业务流PC端与挪动端自适应:页面组件只须要开发一次。不是采纳media query,也不是采纳iframe,而是真正的把手机操控体验带入PC端。只有用一下,就会有一种相逢恨晚的感觉统计值自动更新与推送架构。比方,我有多少待办高深莫测。这是一个通用的架构,能够简便的匹配到任何场景接口对接:微信公众号、企业微信、钉钉企业应用基于Redis的原生分布式架构 QueueScheduleBroadcastCacheStartup基于socketio的音讯推送架构具备部件间数据绑定机制的“仪表板”架构高度定制化的PC端布局:header、sidebar、statusbar相干链接官网: https://cabloy.com/GitHub: https://github.com/zhennann/cabloy

December 21, 2020 · 1 min · jiezi

关于node.js:flexiwan项目踩坑实践后端篇

我的项目背景flexiManage是以色列一家初创公司flexiWAN开源的基于SD-WAN平台的应用层的框架,包含flexiManage服务端框架,基于此服务端框架进行了一些借鉴和改良 目录构造apibillingbinbrokercontrollersdeviceLogiclogginglogsmigrationsmodelsnotificationsperiodicpublicroutesservicesutilswebsocketauthenticate.jsconfigs.jsexpressserver.jsflexibilling.jsmongoConns.jsrateLimitStore.jstoken.js踩坑案例BFF抹掉https的node模块验证[bug形容] 做验证应用服务端及硬件侧未配置ssl,而node启动https模块会默认验证ssl,导致无奈启动服务 [bug剖析] node模块的ssl验证 [解决方案] 起一层bff用于透传接口,后续不便将后续服务层进行微服务化等解决 process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0';const express = require('express');const request = require('request');const app = express();const bodyParser = require('body-parser');const router = express.Router();const SUCC_REG = /^2[0-9]{2}$/app.use(bodyParser.urlencoded({ extended: false }));app.use(bodyParser.json());const headers = { 'authorization': "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJfaWQiOiI1ZmEzYTY5OGZjNDI2ODEwODc3MDYzZDQiLCJ1c2VybmFtZSI6Im1jYWlkYW9Ac2luYS5jb20iLCJvcmciOiI1ZmFkZTkyZDljNGQ2MDQyOWRjN2RhNmMiLCJvcmdOYW1lIjoidHQiLCJhY2NvdW50IjoiNWZhM2E2OThmYzQyNjgxMDg3NzA2M2QzIiwiYWNjb3VudE5hbWUiOiJ0ZXN0IiwicGVybXMiOnsiam9icyI6MTUsImJpbGxpbmciOjMsImFjY291bnRzIjo3LCJvcmdhbml6YXRpb25zIjoxNSwiZGV2aWNlcyI6MTUsInRva2VucyI6MTUsImFwcGlkZW50aWZpY2F0aW9ucyI6MTUsIm1lbWJlcnMiOjE1LCJ0dW5uZWxzIjoxNSwiYWNjZXNzdG9rZW5zIjoxNSwibm90aWZpY2F0aW9ucyI6MTUsInBhdGhsYWJlbHMiOjE1LCJtbHBvbGljaWVzIjoxNX0sImlhdCI6MTYwODExMjcwMiwiZXhwIjoxNjA4NzE3NTAyfQ.LYFv1pBP1540gb-NRCCe4dvbQ0T9HSoZHMkD8xkMFLc", 'Content-Type': 'application/json' }, errMsg = { msg:'unexpected response' }, baseUrl = 'https://10.100.37.101:3443';// 获取所有设施接口app.get('/api/devices',(req,res)=> { console.log(req.url) request({ url: `${baseUrl}${req.url}`, method: 'GET', headers }, (err, response, body) => { console.log(response.statusCode) if(SUCC_REG.test(response.statusCode)) { res.send({code: 200,msg:JSON.parse(response.body)}) } else { res.send(errMsg) } })});// 获取单个设施接口app.get('/api/devices/:id',(req,res)=> { console.log(req.url) request({ url: `${baseUrl}${req.url}`, method: 'GET', headers }, (err, response, body) => { console.log(response.statusCode) if(SUCC_REG.test(response.statusCode)) { res.send({code: 200,msg:JSON.parse(response.body)}) } else { res.send(errMsg) } })});// 获取路由接口app.get('/api/devices/:id/routes',(req,res)=> { console.log(req.url) request({ url: `https://10.100.37.101:3443/api/devices/${req.params.id}/routes`, method: 'GET', headers }, (err, response, body) => { console.log(response.statusCode) if(SUCC_REG.test(response.statusCode)) { res.send({code: 200,msg:JSON.parse(response.body)}) } else { res.send(errMsg) } })});// 启动单个设施app.post('/api/devices/:id/apply/start',(req,res)=> { console.log(req.url); request({ url: `${baseUrl}/api/devices/${req.params.id}/apply`, method: 'POST', headers, body: JSON.stringify({ "method": "start" }) }, (err, response, body) => { let r = JSON.parse(body) if(r.status == 'completed') { res.send({code: 200,msg:'start success'}) } else { res.send({msg: 'start error'}) } })});// 进行单个设施app.post('/api/devices/:id/apply/stop',(req,res)=> { console.log(req.url) request({ url: `${baseUrl}/api/devices/${req.params.id}/apply`, method: 'POST', headers, body: JSON.stringify({ "method": "stop" }) }, (err, response, body) => { let r = JSON.parse(body) if(r.status == 'completed') { res.send({code: 200,msg:'stop success'}) } else { res.send({msg: 'stop error'}) } })});// 同步单个设施app.post('/api/devices/:id/apply',(req,res)=> { console.log(req.url) request.post({ url: `${baseUrl}${req.url}`, headers, body: JSON.stringify({ "method": "sync" }) }, (err, response, body) => { let r = JSON.parse(body) if(r.status == 'completed') { res.send({code: 200,msg:'update success'}) } else { res.send({msg: 'update error'}) } })});// 删除单个设施app.delete('/api/devices/:id',(req,res)=> { console.log(req.url) request({ url: `${baseUrl}${req.url}`, method: 'DELETE', headers }, (err, response, body) => { console.log(response.statusCode) if(SUCC_REG.test(response.statusCode)) { res.send({code: 200,msg:JSON.parse(response.body)}) } else { res.send(errMsg) } })});// 更新设施详情app.put('/api/devices/:id',(req,res)=> { request({ url: `${baseUrl}${req.url}`, method: 'PUT', headers, body: JSON.stringify(req.body) }, (err, response, body) => { console.log('put device', response.statusCode) if(SUCC_REG.test(response.statusCode)) { res.send({code: 200,msg:JSON.parse(response.body)}) } else { res.send(errMsg) console.log('error device', response.statusCode, response.body) } })});// 删除隧道接口app.post('/api/devices/apply/delTunnel',(req,res)=> { console.log('req.body', req.body) request.post({ url: `${baseUrl}/api/devices/apply`, headers, body: JSON.stringify(req.body) }, (err, response, body) => { let r = JSON.parse(body) console.log(r) if(r.status == 'completed') { res.send({code: 200,msg:'删除隧道胜利'}) } else { res.send({msg: r.error}) } })});// 建设隧道接口app.post('/api/devices/apply/createTunnel',(req,res)=> { console.log(req.body) request.post({ url: `${baseUrl}/api/devices/apply`, headers, body: JSON.stringify(req.body) }, (err, response, body) => { let r = JSON.parse(body) console.log(r) if(r.status == 'completed') { res.send({code: 200,msg:r.message}) } else { res.send({msg: r.error}) } })});// 获取所有隧道接口app.get('/api/tunnels',(req,res)=> { console.log(req.url) request({ url: `${baseUrl}${req.url}`, method: 'GET', headers }, (err, response, body) => { console.log(response.statusCode) if(SUCC_REG.test(response.statusCode)) { res.send({code: 200,msg:JSON.parse(response.body)}) } else { res.send(errMsg) } })});app.listen(6000, '127.0.0.1', ()=>{ console.log('app server');});express申请接口申请体不同无奈匹配 ...

December 21, 2020 · 7 min · jiezi

关于node.js:CabloyJS也有工作流引擎了是你想要的吗

前言家喻户晓,NodeJS作为后端开发语言和运行环境,样样都好,就差一个NodeJS工作流引擎。CabloyJS 4.0重点开发了NodeJS工作流引擎,并作为内置的根底外围模块,近一步拓展了NodeJS在后端的利用场景,为深刻研发各类商业业务逻辑,提供了根底撑持 NodeJS工作流引擎的特点更简便的配置:采纳JSON进行流程定义的配置,辞别XML配置文件的繁杂流程定义:反对历史版本、反对启用/禁用更清晰的架构:采纳三个外围模块用分层的机制实现工作流引擎的架构,让工作流不再神秘,源码也不再叠床架屋模块名称阐明a-flow流程定义、流程实例a-flownode流程节点(流动节点)a-flowtask流程工作反对业务流程和审批流程与Atom三生三世联合,内置了一套基于Atom的审批工作流。参见:原子阶段(三生三世)与表单验证联合,反对别离配置不同流程节点的读取字段权限和批改字段权限。参见:表单验证可通过AOP机制定制工作流逻辑可通过Listener机制定制工作流逻辑开放式的架构,反对更多流程节点的定制开发蕴含大量测试驱动代码,可疾速上手应用工作流工作流演示新建一个草稿:洽购订单抉择要应用的流程定义,而后提交,草稿进入相应的审批流程签收工作、并解决工作流程完结,草稿转为归档 一个最简工作流定义src/module/test-flow/backend/src/config/static/flowDef/set00_simple.js { listener: null, process: { nodes: [ { id: 'startEvent_1', name: 'Start', type: 'startEventNone', }, { id: 'endEvent_1', name: 'End', type: 'endEventNone', }, ], edges: [ { id: 'edge_1', source: 'startEvent_1', target: 'endEvent_1', }, ], }, }名称阐明listener监听器,可监听flow/node/task各类事件process.nodes流程节点process.nodes.type流程节点类型process.edges流程转移线process.edges.source起源process.edges.target去向一个审批流程定义src/module/test-flow/backend/src/config/static/flowDef/set01_atomUserTask.js { listener: null, process: { nodes: [ { id: 'startEvent_1', name: 'Drafting', type: 'startEventAtom', options: { atom: { module: moduleInfo.relativeName, atomClassName: 'purchaseOrder', }, conditionExpression: 'atom._flowDefKey==='set01_atomUserTask'', }, }, { id: 'activity_1', name: 'Review', type: 'activityUserTask', options: { assignees: { // users: '1,2', // roles: '1,2', vars: 'flowUser', }, confirmation: false, bidding: false, completionCondition: { // passed: 1, // rejected: '100%', }, // rejectedNode:null, // allowRejectTask: true, // allowCancelFlow: false, schema: { write: [ 'atomName', { name: 'description', property: { type: 'string', ebType: 'text', ebTitle: 'Description', }, }, ], }, }, }, { id: 'endEvent_1', name: 'End', type: 'endEventNone', }, ], edges: [ { id: 'edge_1', source: 'startEvent_1', target: 'activity_1', }, { id: 'edge_2', source: 'activity_1', target: 'endEvent_1', }, ], }, }process.nodes.type名称阐明startEventAtom开始事件节点(起草):通过options.atom和options.conditionExpression与指定的Atom类型绑定。当指定的Atom提交时主动启动相匹配的工作流定义activityUserTask用户工作节点:可指定参加人、是否竞签、实现条件、读字段权限、写字段权限,等等endEventNone完结事件节点相干链接官网: https://cabloy.com/GitHub: https://github.com/zhennann/cabloy

December 20, 2020 · 1 min · jiezi

关于node.js:JBrowse-安装方式

在window环境下装置环境要求cmdNode.js 10.4+首先是装置 node ,在网络上有很多这样的教程,如果你还有额定的对于node版本的管制需要,能够应用 nvm 对 node 版本进行下载和选用。在其中可能须要用到一些其余的软件:比方 Git 装置形式step1:全局或部分装置 jbrowse :1、全局: npm install -g @jbrowse/cli 2、部分: npx @jbrowse/clistep2:应用 jbrowse create 下载JBrowse 2:jbrowse create jbrowse2 , 还能够间接在 GitHub 下载相应的压缩包而后解压。应用形式这个软件相似于一个网页,只不过须要使用者本人开启本地服务能力应用,因而只须要装置了node的机器,在装置了jbrowse的文件夹下输出 npx serve .。

December 19, 2020 · 1 min · jiezi

关于node.js:Node和npm-安装环境配置Windows

Node装置:1.官网下载最新的node安装包http://nodejs.cn/download/ 2.装置node双击msi文件,呈现以下界面,始终点击直到装置胜利 3.关上命令管理器,输出node -v 查看版本是否装置胜利 NPM装置:node是自带npm的,如果想要降级,能够运行以下命令: npm install npm -g ![image.png](/img/bVcLRnZ)

December 19, 2020 · 1 min · jiezi

关于node.js:基于-ThinkJS-的云开发体验

背景ThinkJS 是一款企业级的 Node.js Web 开发框架,致力于集成我的项目最佳实际,标准我的项目让企业级团队开发变得更加简略,更加高效。 它基于 Koa 2.0 开发,兼容 Koa 的所有 Middleware。 内核玲珑,反对 Adapter, Extend 等多种插件扩大形式,框架内的大部分性能也是通过这些形式进行扩大的。 性能优异,反对 TypeScript。 云开发 CloudBase 是云原生一体化利用研发平台为开发者提供高可用、主动弹性扩缩的后端云服务,蕴含计算、存储、托管等能力,可用于云端一体化开发多种端利用(小程序、公众号、Web 利用、Flutter 客户端等),帮忙开发者对立构建和治理后端服务和云资源,防止了利用开发过程中繁琐的服务器搭建及运维,开发者能够专一于业务逻辑的实现,开发门槛更低,效率更高。 在云开发中应用ThinkJS其实在云开发中应用 ThinkJS 和咱们日常应用大同小异,除了启动文件须要依照云开发的要求批改一下以外,外部的业务逻辑根本不须要改变。 咱们能够应用云开发的 CLI 工具疾速的初始化一个适配云开发的 ThinkJS 我的项目。 其中 thinkjs-app 是你的我的项目文件夹名称。 tcb new thinkjs-app thinkjs-starter初始化结束进入我的项目目录后执行 npm install 装置好依赖,就能够通过 npm start 启动开发环境了。 如果一切正常,你能够通过拜访 http://127.0.0.1:8360 看到经典的 ThinkJS 的初始化界面了。 之后咱们就能够欢快的进行我的项目的开发了。 当我的项目开发结束之后,间接执行如下命令,CLI 工具就会将咱们的代码部署到云函数上啦! 由此可见,通过云开发,咱们的开发部署流程变的更加简略了。买通流程之后具体就是业务逻辑的开发了,对于更多 ThinkJS 和云开发的开发指南可参见官网文档 。 除了上述的云函数,云开发还提供了云数据库和云存储服务不便咱们的我的项目疾速接入相干服务。 数据库这块是比拟经典的 NoSQL 的数据库操作,应用云开发的 SDK 能够十分不便的进行操作。 const cloudbase = require(‘@cloudbase/node-sdk’);const app = cloudbase.init({…});const db = app.database();const _ = db.command;let userInstance = db.collection(‘User’);userInstance = userInstance.where({create_time: _.gt(new Date(2020, 0, 1))});const users = await userInstance.get();大家能够间接通过在 ThinkJS 中调用 SDK 的办法实现数据库的查问操作。 ...

December 17, 2020 · 1 min · jiezi

关于node.js:JavaScript-基础数据类型

根底数据类型转载请注明出处,github 地址 JavaScript 根底数据类型js中的数据类型JavaScript 中共有七种内置数据类型,包含根本类型和对象类型。 根本类型根本类型分为以下六种: string(字符串)boolean(布尔值)number(数字)symbol(符号)null(空值)undefined(未定义)留神: string 、number 、boolean 和 null undefined 这五种类型统称为原始类型(Primitive),示意不能再细分上来的根本类型;symbol是ES6中新增的数据类型,symbol 示意举世无双的值,通过 Symbol 函数调用生成,因为生成的 symbol 值为原始类型,所以 Symbol 函数不能应用 new 调用;null 和 undefined 通常被认为是非凡值,这两种类型的值惟一,就是其自身。对象类型对象类型也叫援用类型,array和function是对象的子类型。对象在逻辑上是属性的无序汇合,是寄存各种值的容器。对象值存储的是援用地址,所以和根本类型值不可变的个性不同,对象值是可变的。 弱类型语言JavaScript 是弱类型语言,而且JavaScript 申明变量的时候并没有预先确定的类型,变量的类型就是其值的类型,也就是说变量以后的类型由其值所决定,夸大点说上一秒种的String,下一秒可能就是个Number类型了,这个过程可能就进行了某些操作产生了强制类型转换。尽管弱类型的这种不须要预先确定类型的个性给咱们带来了便当,同时也会给咱们带来困扰,为了能充分利用该个性就必须把握类型转换的原理。 js中的强制转换规则ToPrimitive(转换为原始值)ToPrimitive对原始类型不产生转换解决,只针对援用类型(object)的,其目标是将援用类型(object)转换为非对象类型,也就是原始类型。 ToPrimitive 运算符承受一个值,和一个可选的冀望类型作参数。ToPrimitive 运算符将值转换为非对象类型,如果对象有能力被转换为不止一种原始类型,能够应用可选的 冀望类型 来暗示那个类型。 转换后的后果原始类型是由冀望类型决定的,冀望类型其实就是咱们传递的type。间接看上面比较清楚。ToPrimitive办法大略长这么个样子具体如下。 /*** @obj 须要转换的对象* @type 冀望转换为的原始数据类型,可选*/ToPrimitive(obj,type)type不同值的阐明type为string:先调用obj的toString办法,如果为原始值,则return,否则进行第2步调用obj的valueOf办法,如果为原始值,则return,否则进行第3步抛出TypeError 异样type为number:先调用obj的valueOf办法,如果为原始值,则return,否则进行第2步调用obj的toString办法,如果为原始值,则return,否则第3步抛出TypeError 异样type参数为空该对象为Date,则type被设置为String否则,type被设置为NumberDate数据类型非凡阐明:对于Date数据类型,咱们更多冀望取得的是其转为工夫后的字符串,而非毫秒值(工夫戳),如果为number,则会取到对应的毫秒值,显然字符串应用更多。其余类型对象依照取值的类型操作即可。 ToPrimitive总结ToPrimitive转成何种原始类型,取决于type,type参数可选,若指定,则依照指定类型转换,若不指定,默认依据实用状况分两种状况,Date为string,其余对象为number。那么什么时候会指定type类型呢,那就要看上面两种转换形式了。 toStringObject.prototype.toString() toString() 办法返回一个示意该对象的字符串。 每个对象都有一个 toString() 办法,当对象被示意为文本值时或者当以冀望字符串的形式援用对象时,该办法被主动调用。 这里先记住,valueOf() 和 toString() 在特定的场合下会自行调用。 valueOfObject.prototype.valueOf()办法返回指定对象的原始值。 JavaScript 调用 valueOf() 办法用来把对象转换成原始类型的值(数值、字符串和布尔值)。然而咱们很少须要本人调用此函数,valueOf 办法个别都会被 JavaScript 主动调用。 不同内置对象的valueOf实现: String => 返回字符串值Number => 返回数字值Date => 返回一个数字,即工夫值,字符串中内容是依赖于具体实现的Boolean => 返回Boolean的this值Object => 返回this对照代码会更清晰一些: ...

December 16, 2020 · 3 min · jiezi

关于node.js:npm包里的packagejson文件

先看下目前node包里的package.json文件配置 { "name": "webpack-learn", // 包名 个别采纳中划线或者下划线,不倡议采纳小驼峰的模式命名 "version": "1.0.0", // 版本 "description": "vue webpack", "main": "dist/main.js", "module": "dist/main.js", "scripts": { "dev": "webpack-dev-server --progress --config build/webpack.config.dev.js --inline --hot", "build": "webpack --progress --config build/webpack.config.prod.js", }, "keywords": [ "webpack init project", "webpack", "init Project", "vue" ], "engines": { "node": ">= 6" // node环境要求 }, "author": "cpp", "license": "ISC", "homepage": "https://github.com/niaogege/webpack-learn", // 我的项目介绍主页 "repository": { "type": "git", "url": "https://github.com/niaogege/webpack-learn.git" }, "files": [ "dist", "src", "public" ], "dependencies": { "vue": "^2.6.12" }, "devDependencies": { "babel-core": "^6.26.3", "babel-loader": "^8.2.2", "clean-webpack-plugin": "^3.0.0", ... }}main / moduleMain property in package.json defines package entry point 定义包的进口简略说: 供我的项目用import导入的入口,次要作用是裸露此依赖包的进口,比方vue源码里的package.json中这么定义的 ...

December 13, 2020 · 1 min · jiezi

关于node.js:用原生nodejs写了一个傻瓜爬虫爬了一本书哈哈

突发奇想想在网上爬一本书,就轻易创立了个js文件开始写。 内容如下: var axios = require('axios')var cheerio = require('cheerio')var fs = require('fs')// 创立文件夹if(!fs.existsSync('text')) { fs.mkdirSync('text')}// 请求书的地址const baseUrl = 'https://www.shutxt.com/shaoer/18971'const charpterFirst = 1064743const charpterLast = 1064757for(let i = charpterFirst; i < charpterLast + 1; i++) { axios.get(`https://www.shutxt.com/shaoer/18971/${i}.html`).then(res => { var $ = cheerio.load(res.data) var title = $('title').text().split('_')[0] var p = $('.zw p') var content = '' for (let i = 0; i < p.length; i++) { var li = p.eq(i).text() content += li + '\r\n\r\n' } const article = title + '\r\n\r\n\r\n' + content fs.writeFileSync(`./text/${title}.txt`, article, 'utf-8', (err) => { if(err) console.log('写文件出错了,谬误是:' + err) else console.log(title + ':ok') })})}而后胜利的爬下来了一本书(十分傻瓜式),开心~ ...

December 9, 2020 · 1 min · jiezi

关于node.js:n-模块切换-node-版本无效的解决办法

问题概述全局装置 n 模块 npm install -g n`装置最新稳定版 node 版本 n stable`这样就装置到最新版本。 应用 n 切换版本 n # 呈现 node/8.12.0 node/11.0.0` 抉择 11.0.0 版本回车, node -v# 8.12.0` 解决办法查看 node 装置门路# /usr/local/bin/node` 而 n 默认装置门路是 /usr/local,若你的 node 不是在此门路下,n 切换版本就不能把 bin、lib、include、share 复制该门路中,所以咱们必须通过 N_PREFIX 变量来批改 n 的默认 node 装置门路。应用vim 编辑 vim .bash_profile 文件,在结尾处增加两行。export N_PREFIX=/usr/local/bin/node #依据你的装置门路而定export PATH=$N_PREFIX/bin:$PATH` 保留,刷新文件。source .bash_profile`重新安装n stable`从新切换版本即可,依据提醒可能要授予 sudo 权限。 node -v # 11.0.0Node 批改默认镜像源在应用Node 装置依赖的时候,装置速度会很慢,默认镜像源地址:https://registry.npmjs.org, 咱们能够通过批改仓库地址来放慢装置速度。能够通过 npm config get registry 来查看以后镜像源。 ...

December 9, 2020 · 1 min · jiezi

关于node.js:eggmysql配置多数据源

刚刚有小朋友问B老师:egg怎么配置多个数据源呀,网上那些死劲儿不好用那B老师给大家解释下怎么配置个别不会配置多数据源的敌人是没有看清官网对于配置多数据源的代码(有点坑) 单个数据源config.mysql外面的client不带s多个数据源config.mysql外面的client带s //单个数据源client//多个数据源clients import { EggAppConfig, EggAppInfo, PowerPartial } from "egg";export default (appInfo: EggAppInfo) => { const config = {} as PowerPartial<EggAppConfig>; // override config from framework / plugin // use for cookie sign key, should change to your own and keep security config.keys = appInfo.name + "_1606967424562_9661"; // add your egg config in here config.middleware = []; // add your special config in here const bizConfig = { sourceUrl: `https://github.com/eggjs/examples/tree/master/${appInfo.name}`, }; //连贯服务器 config.mysql = { //database configuration //单个数据源client //client: { //host //host: "localhost", //port //port: "3306", //username //user: "root", //password //password: "root", //database //database: "egg", //}, //多个数据源clients clients: { db1: { //host host: "localhost", //port port: "3306", //username user: "root", //password password: "root", //database database: "egg", }, db2: { //host host: "localhost", //port port: "3306", //username user: "root", //password password: "root", //database database: "hubeiwh", }, }, // 所有数据库配置的默认值 default: {}, //load into app,default is open //加载到应用程序,默认为关上 app: true, //load into agent,default is close //加载到代理中,默认值为“敞开” agent: false, }; // the return config will combines to EggAppConfig return { ...config, ...bizConfig, };};而后去服务外面应用数据库 ...

December 8, 2020 · 2 min · jiezi

关于node.js:用-vscode调试nodejs-时提示对应的-grpc-模块找不到

报错提醒如下: ERROR 2020-12-07 15:31:14,835 v1(6) [gulu-core]::UncaughtException 10.79.185.0 - - default - Error: Failed to load gRPC binary module because it was not installed for the current systemExpected directory: node-v67-darwin-x64-unknownFound: [node-v83-darwin-x64-unknown]This problem can often be fixed by running "npm rebuild" on the current systemOriginal error: Cannot find module '/Users/chenwei/repos/kunpeng/node_modules/grpc/src/node/extension_binary/node-v67-darwin-x64-unknown/grpc_node.node' at Object.<anonymous> (/Users/chenwei/repos/kunpeng/node_modules/grpc/src/grpc_extension.js:53:17) at Module._compile (internal/modules/cjs/loader.js:738:30) at Module._extensions..js (internal/modules/cjs/loader.js:749:10) at Object.require.extensions.(anonymous function) [as .js] (/Users/chenwei/repos/kunpeng/node_modules/ts-node/src/index.ts:851:44) at Module.load (internal/modules/cjs/loader.js:630:32) at tryModuleLoad (internal/modules/cjs/loader.js:570:12) at Function.Module._load (internal/modules/cjs/loader.js:562:3) at Module.require (internal/modules/cjs/loader.js:667:17) at require (internal/modules/cjs/helpers.js:20:18) at Object.<anonymous> (/Users/chenwei/repos/kunpeng/node_modules/grpc/src/client_interceptors.js:144:12)Waiting for the debugger to disconnect...调试了一下grpc模块,发现是调试模式下,node运行时的版本不对: ...

December 7, 2020 · 1 min · jiezi

关于node.js:nodejs事件和事件循环简介

简介相熟javascript的敌人应该都应用过事件,比方鼠标的挪动,鼠标的点击,键盘的输出等等。咱们在javascript中监听这些事件,从而触发相应的解决。 同样的nodejs中也有事件,并且还有一个专门的events模块来进行专门的解决。 同时事件和事件循环也是nodejs构建异步IO的十分重要的概念。 明天咱们来具体理解一下。 事件nodejs为事件提供了一个专门的模块:lib/events.js。 还记得咱们在讲应用nodejs构建web服务器吗? const server = http.createServer((req, res) => { res.statusCode = 200 res.setHeader('Content-Type', 'text/plain') res.end('welcome to www.flydean.com\n')})这里,每个申请都会触发request事件。 nodejs的外围API是基于异步事件驱动来进行架构的,所以nodejs中有十分多的事件。 比方:net.Server 会在每次有新连贯时触发事件,fs.ReadStream 会在关上文件时触发事件,stream会在数据可读时触发事件。 咱们看一下怎么来构建一个nodejs的事件: const EventEmitter = require('events')const eventEmitter = new EventEmitter()events罕用的办法有两个,别离是on和emit。 on用来监听事件,emit用来触发事件。 eventEmitter.on('fire', () => { console.log('停火')})eventEmitter.emit('fire')emit还能够带参数,咱们看下一个参数的状况: eventEmitter.on('fire', who => { console.log(`停火 ${who}`)})eventEmitter.emit('fire', '美帝')再看看两个参数的状况: eventEmitter.on('fire', (who, when) => { console.log(`停火 ${who} ${when}`)})eventEmitter.emit('fire', '川建国','now')默认状况下,EventEmitter以注册的程序同步地调用所有监听器。这样能够确保事件的正确排序,并有助于防止竞态条件和逻辑谬误。 如果须要异步执行,则能够应用setImmediate() 或者 process.nextTick()来切换到异步执行模式。 eventEmitter.on('fire', (who, when) => { setImmediate(() => { console.log(`停火 ${who} ${when}`); });})eventEmitter.emit('fire', '川建国','now')除此之外,events还反对其余几个办法: ...

December 6, 2020 · 2 min · jiezi

关于node.js:mongo定义Schema并灵活创建读取mongo33

1.配置conf.jsmodule.exports = { db: { url: 'mongodb://127.0.0.1:27017/local', options: { useNewUrlParser: true, } }}2.入口index.jsconst Koa = require('koa');const app = new Koa();const config = require('./conf')const {loadModel} = require('./framework/loader')// 加载model的配置对应字段loadModel(config)(app)// 引入动静配置的apiconst rest = require('./framework/router');// 主动将传入的body字符串转换对象值,cxt.request.bodyconst bodyParser = require('koa-bodyparser'); app.use(bodyParser());app.use(rest);const port = 3000;app.listen(port, () => { console.log('link 3000');})3.定义Schema./model/user.jsmodule.exports = { schema: { mobile: { type: String, required: true, }, realName: { type: String, required: true, }, }}4.加载定义的Schema文件,并读取配置到mongo./framework/loader.jsconst fs = require('fs');const path = require('path');const mongoose = require('mongoose');function load (dir, cb) { // 获取绝对路径 const url = path.resolve(__dirname, dir); const files = fs.readdirSync(url); files.forEach(filename => { filename = filename.replace('.js', ''); const file = require(url + '/' + filename); cb(filename, file); })}const loadModel = (config) => { return (app) => { mongoose.connect(config.db.url, config.db.options); const conn = mongoose.connection; conn.on('error', () => { console.error('连贯失败') }) app.$model = { } load('../model', (filename, {schema}) => { console.log('load model '+ filename, schema) app.$model[filename] = mongoose.model(filename, schema) }) }}module.exports = { loadModel}以上步骤,即可定义在mongo数据库中的数据模型,接下来是将数据模型和接口对应 ...

December 6, 2020 · 2 min · jiezi

关于node.js:前后端开发中简易设置个性化的Web代理服务器

应用 live-serverNode.js 我的项目开发调试时前端我的项目时通常须要提供web服务器,能力实现一些页面的性能调试。因为如果通过file://协定拜访html或js时,与相比 http://协定平安方面差异较大,file://拜访文件时无奈传递http协定头之类的货色,所以搭建web服务器成为了必须选项。 很多ide主动提供了这样的性能,如HBuilder. 本人搭建动态的web服务器也很容易,live-server这个node.js开发的软件就很好用。 live-server装置应用都很简略:装置: npm install -g live-server 应用: live-server --port=9090能够指定绑定的ip和端口号,也能够指定证书来配置对 https 协定的反对。live-server 可能主动监控文件变动从而本人从新加载页面,对前端开发来说十分不便。 搭建动态 Web 服务器但也有一些状况下须要进行一些客户化设定,比方前后端拆散我的项目,须要拜访后端接口时,须要进行跨域的配置,如果应用代理形式的话,就可更加灵便的形式,而不用批改后端代码(因为这些批改经常是在正式公布后是不须要的,因为生产环境可能由网关实现跨域配置,或是同域的基本不须要跨域配置)。 这时本人能过简略的js文件实现一个代理的 web 服务器便很不便。 搭建一个能够拜访动态文件的web服务器大体只须要以下的代码: "use strict";const fs = require('fs');const path = require('path');const http = require('http');const url = require('url');const PORT = 3000;const args = process.argvlet staticBasePath = '../dist';if(args.length>2) staticBasePath = args[2];const staticServe = function(req, res) { const resolvedBase = path.resolve(staticBasePath); const safeSuffix = path.normalize(req.url).replace(/^(\.\.[\/\\])+/, ''); const fileLoc = path.join(resolvedBase, safeSuffix); let pathname = url.parse(req.url).pathname; //依据url失去文件门路,读取文件并返回给客户端 fs.readFile(fileLoc, function(err, data) { if (err) { res.writeHead(404, 'Not Found'); res.write('404: File Not Found!'); return res.end(); } res.statusCode = 200; res.write(data); return res.end(); });};const httpServer = http.createServer(staticServe);httpServer.listen(PORT);fs, http, path, url都是node.js自带的模块,在以上简略的状况下,不须要装置额定的模块即可实现对js,html,css,图片的动态文件的拜访。 ...

December 6, 2020 · 2 min · jiezi

关于node.js:前端开源实战项目推荐

前言这段时间始终有学员和一些正在从事前端开发工作的敌人询问“有没有举荐的前端开源我的项目?”,因为始终忙于工作没有工夫去整顿,明天应各位的申请,我整顿了一些开源我的项目 。举荐程序与我的项目的好坏无关,框架的举荐程序就大家询问的比例来分,跟以后市场框架的占有率无关,所以大家不要先入为主的认为我列在后面的可能就是好的。话不多说,咱们进入正题。 Vue.jsVue Element Adminvue-element-admin 是一个后盾前端解决方案,它是基于 element-ui 实现的。 我的项目地址:vue-element-admin 我的项目成果查看:vue-element-admin-dashboard Iview Adminiview-admin 是一个基于 iView 的 Vue 2.0 管理系统模板 我的项目地址:iview-admin Vue2 Managevue2-manage 是基于 vue + element-ui 的后盾管理系统 我的项目地址:vue2-manage 我的项目有台管理系统成果查看:back-manage 我的项目前端手机模仿预览:elm-manage Vue Manage Systemvue-manage-system 是基于 Vue.js + Element UI 的后盾管理系统解决方案 vue-manage-system 登录界面 vue-manage-system 首页( 默认皮肤 ) vue-manage-system 首页( 浅绿色皮肤 ) 我的项目地址:vue-manage-system Vue Music Webappvue-music-webapp 是基于 Vue(2.5) + vuex + vue-router + vue-axios +better-scroll + Scss + ES6 等开发一款挪动端音乐 WebApp 我的项目 ...

December 5, 2020 · 2 min · jiezi

关于node.js:使用node创建接口查询mongo返回结果在接口中

1. 初始化一些测试数据,清空原有的数据并插入100条测试数据node initData.jsinitData.jsconst mongodb = require('./models/db');mongodb.once('connect', async () => { const col = mongodb.col('fruits'); // 删除已存在的数据 await col.deleteMany(); const data = new Array(100).fill().map((value, index) => { return { name: 'XXXX' + index, price: index, category: Math.random() > 0.5 ? '蔬菜' : '水果', } }) // 插入新建的数据 await col.insertMany(data); console.log('插入测试数据胜利');})models/db.jsconst conf = require('./conf');const { EventEmitter } = require('events'); // 数据库异步连贯工具// 客户端const { MongoClient } = require('mongodb');class Mongodb { constructor(conf) { this.conf = conf; this.emmiter = new EventEmitter(); // 连贯 this.client = new MongoClient(conf.url, { useNewUrlParser: true, }) this.client.connect(err => { console.log(err); if (err) { throw err; } console.log('连贯失常'); this.emmiter.emit('connect') }) } col(colName, dbName = conf.dbName) { return this.client.db(dbName).collection(colName); } once(event, cb) { this.emmiter.once(event, cb) }}module.exports = new Mongodb(conf)models/conf.jsmodule.exports = { url: 'mongodb://127.0.0.1:27017', dbName: 'local',}2. 对外接口应用http://localhost:3000/api/list?keyword=20拜访接口,并传参pageNum、pageSize、category、keyword查问 ...

December 5, 2020 · 2 min · jiezi

关于node.js:即使不会nodejs拖拽就可完成数据的可视化展示

摘要:node-red是一款基于Node.js的开源可视化界面开发工具,不须要把握node.js而通过拖拽即可实现数据的可视化展现。1.首先看一下node-red对数据的渲染成果 你可能认为,必须熟练掌握前端常识能力做出这样的页面,实际上它只须要一下几步拖拽操作即可 node-red自身就是为MQTT而诞生,因而很适宜进行物联网数据展现,反对数据库操作、mqtt协定,同时用户也能够在它的根底上,应用html等进行前端界面批改。如果你想疾速而完满的展现你的数据,无妨试一试NODE-RED。当然,你想装置它,也很简略的~~ 2.装置首先须要装置nodejs(百度上有很多示例,也挺简略的,就不解说啦),而后 在控制台输出 npm install -g --unsafe-perm node-red 即可; 为了让node-red在后盾放弃运行,咱们应用此命令:nohup node-red & 残缺的装置步骤如下 装置nodejs环境sudo apt-get install nodejs装置node-redsudo apt-get install npmsudo npm install -g node-red一般运行node-red后盾继续运行nohup node-red &3.应用示例展现一下我本人展现温湿度的页面 nede-red这款工具,好用而且简略,很适宜初学者。给大家分享一下我的数据展现,附源码(页面交丑,仅供交流学习)其中包含连贯mqtt服务器、数据插入mysql数据库 数据展现页面 在上面这个界面中,我进行了两个温度、两个湿度数据的展现;当订阅的主题承受到音讯后,解析json数据格式,失去温湿度数据并展现在前端 布局:留神,在此布局中,有应用到数据库。我应用的是mysql,只是简略的插入数据,仅供参考。 紫色的方块为订阅的MQTT音讯,须要配置相应的参数绿色为调试信息;蓝色方块为布局的展现,不同部件,展现的成果不同黄色方块为信息格式转化,次要是为了不便折线图的展现;橙色方块为数据库操作,须要连贯本人的数据库; 其实实现很简略,就是通过利落、而后设置相应的参数,基本上不要求编程能力。而且,只有有数据,就能够通过nodered去展现。 点击关注,第一工夫理解华为云陈腐技术~

December 4, 2020 · 1 min · jiezi

关于node.js:javascript开发后端程序的神器nodejs

简介javascript尽管始终都能够做服务端编程语言,然而它更多的是以客户端编程语言来展现在世人背后的。兴许javascript本人都遗记了还能够做服务器端编程,直到2009年nodejs的横空出世。 nodejs的历史javascript作为一门解释性语言,是不须要像C或者C++那样进行编译的。然而在晚期的时候,javascript引擎的执行效率是比拟低的,所以导致javascript只能做做dom操作。 随着ajax的衰亡和古代web2.0的技术的倒退,支流浏览器开发商尽可能的晋升javascript的执行效率,最初Chrome V8呈现了,Chrome V8是 Chromium 我的项目开源的 JavaScript 引擎,使得javascript的执行效率失去了极大的晋升。 nodejs借着V8浴火重生了。 nodejs从一诞生就取得了极大的关注。比拟javascript的开发者还是十分十分多的。而且一门语言能够通用前后端是如许的有吸引力。 nodejs从2009年倒退到2020年的nodejs 14,经验了11年的历史,和它的先辈javascript相比还是很年老,然而因为其开放性和包容性,nodejs在以一个十分快的速度向前倒退。 nodejs简介nodejs借助于V8引擎和一组异步的 I/O 原生性能,极大的晋升了nodejs的解决效率。 异步IO咱们大家应该都很分明,和同步IO相比,线程不必阻塞,能够去解决其余更有意义的事件。只是在响应返回的时候复原操作,所以不会节约CPU工夫。 咱们简略看一下nodejs的IO模型: 一个好的语言须要有良好的生态系统相配合,因为语言自身只能提供最根本的一些操作,咱们还须要第三方零碎来丰盛这个语言的生态。 而nodejs的npm仓库,托管着寰球最大的开源库生态系统。 基本上应用nodejs你能够实现绝大多数须要的性能。 nodejs的另外一个特点就是简略,考虑一下咱们最罕用的web利用,如果用java来写,十分麻烦,你还须要一个web服务器。 在nodejs中,一切都是那么的简略: const http = require('http')const hostname = '127.0.0.1'const port = 3000const server = http.createServer((req, res) => { res.statusCode = 200 res.setHeader('Content-Type', 'text/plain') res.end('welcome to www.flydean.com\n')})server.listen(port, hostname, () => { console.log(`please visit http://${hostname}:${port}/`)})下面的代码就创立了一个web服务,监听在3000端口, 咱们首先引入了http模块,用来进行http解决。 接着应用http 的 createServer() 办法会创立新的 HTTP 服务器并返回它。 在createServer办法外部,咱们能够设定要返回的对象。 最初启用server.listen性能,来监听特定的端口和服务器,当服务就绪之后,会调用前面的回调函数,执行特定的命令。 每当接管到新的申请的时候,就会触发request事件,request事件能够传递两个参数: request 是一个http.IncomingMessage对象,提供了申请的详细信息。response 是一个http.ServerResponse对象,用于返回数据给调用方。在下面的例子中,咱们并没有应用request,而是应用response间接构建了返回的对象。 ...

December 4, 2020 · 4 min · jiezi

关于node.js:山东标梵简单分析下-Nodejs-关于集群的那些事

须要理解的根底概念 一个应用程序中,至多蕴含一个过程,一个过程至多蕴含一个线程。 过程(Process)是计算机中的程序对于某数据汇合上的一次运行流动,是零碎进行资源分配和调度的根本单位线程(Thread)是操作系统可能进行运算调度的最小单位。它被蕴含在过程之中,是过程中的理论运作单位。Node 的特点: 主线程是单过程(前面版本呈现了线程概念,开销较大);基于事件驱动,异步非阻塞 I/O;可用于高并发场景。nodejs 原有版本中没有实现多线程,为了充分利用多核 cpu,能够应用子过程实现内核的负载平衡。 node 须要解决的问题: node 做耗时的计算时候,造成阻塞。node 如何开启子过程开发过程中如何实现过程守护概念太多,咱们从具体案例动手,看看单线程到底会带来什么问题。 单线程的毛病// file: question.jsconst http = require('http');http.createServer((req, res) => { if (req.url === '/sum') { // 求和 var endTime = new Date().getTime() + 10000while (new Date().getTime() < endTime) {}res.end('sum')} else { res.end('end');}}).listen(3000);操作步骤 node question.js关上浏览器,在一个 tab1 上拜访 /sum 。疾速关上另一个 tab2,拜访 / 。请问会呈现什么景象? 咱们发现 tab1 在转圈, tab2 也在转圈,这个景象就很奇怪了。tab1 在转圈咱们能够了解,因为咱们须要破费是 10s,然而 tab2 也须要 10s 后,能力被拜访。这就很奇怪了。 这个问题就相当于,他人拜访这个浏览器阻塞了 10s,你也要跟着阻塞 10s。这个问题就很难被承受了。因而得出结论,node 不太适宜做 cpu 密集型的服务。 ...

December 2, 2020 · 4 min · jiezi

关于node.js:万字长文深度剖析面向对象的javascript

简介本将会深刻解说面向对象在javascript中的利用,并具体介绍三种对象的生成形式:构造函数,原型链,类。 什么是对象尽管说程序员不缺对象,随时随地都能够new一个进去,然而在程序的世界中,对象到底是什么呢? 对象是单个实物的形象。 对象是一个容器,封装了属性(property)和办法(method)。 而面向对象是绝对于面向过程来讲的,面向对象办法,把相干的数据和办法组织为一个整体来对待,从更高的档次来进行零碎建模,更贴近事物的天然运行模式。 面向对象的益处就是可形象,封装和可重用性,同时提供了继承和多态等十分有用的个性。 而随着JS的倒退,曾经超过了最开始的脚本语言,尤其是nodejs的呈现之后,更是极大的丰盛了js的工作能力。 所以JS也须要进行对象化。 一般来说,在JS中构建对象有三种形式: 构造函数(constructor)原型链(prototype)类(class) ---ES6提供接下来,咱们一一来解说。 构造函数构造函数是专门用来生成对象的函数。它提供模板,形容对象的根本构造。 一个构造函数,能够生成多个对象,这些对象都有雷同的构造。构造函数的写法就是一个一般的函数,然而有本人的特色和用法. var Book = function () { this.name = 'www.flydean.com';}Book就是构造函数,它提供模板,用来生成实例对象。为了与一般函数区别,构造函数名字的第一个字母通常大写。 构造函数的特点构造函数首先是一个函数,也就是说是function结尾的函数。其次函数体外部应用了this关键字,代表了所要生成的对象实例。 在应用构造函数的时候,必须用new命令,调用Book函数。 new命令的作用,就是执行构造函数,返回一个实例对象。 var Book = function () { this.name = 'www.flydean.com';}var b1 = new Book();console.log(b1.name);下面的例子输入后果: www.flydean.com如果咱们忘了应用new,会产生什么状况呢? var Book = function () { this.name = 'www.flydean.com';}var b2 = Book();console.log(name);console.log(b2.name);第一个输入会输入www.flydean.com 而第二个则会报一个谬误: TypeError: Cannot read property 'name' of undefined因为这样调用的this指向的是global,所以this.name变成了全局变量。 为了防止这种遗记写new的问题,能够在第一行加上use strict,在严格模式中,函数外部的this不能指向全局对象,默认等于undefined,导致不加new调用会报错。 如果不想应用use strict,则能够在构造函数外部判断是否应用new命令,如果发现没有应用,则间接返回一个实例对象。 function Person(firstname,lastname){ if(!(this instanceof Person)){ return new Person(firstname,lastname); } this.firstname= firstname; this.firstname = lastname;}console.log(Person("jack","ma").firstname);console.log((new Person("jack","ma")).firstname);new命令的原理应用new命令时,它前面的函数调用就不是失常的调用,而是顺次执行上面的步骤: ...

December 2, 2020 · 4 min · jiezi

关于node.js:极大提高国人开发效率超实用的-VS-Code-插件

置信好多英语不好的同学在打代码的时候,常常会遇到不懂的单词,也置信好多时候同学写我的项目时候遗记框架的接口,须要网上翻阅文档,线上发问求助,参考其余我的项目的示例,那么如果你都过遇到这类问题,那么置信这款 VS Code 插件能极大的帮忙到你,它能让您在代码中进行线上/线下搜寻,或者翻译的。 应用介绍下简略的应用过程,你能够在 VS Code 中搜寻 Search/Translate Hero 而后点击装置,你也能够在这里进行下载: https://marketplace.visualstudio.com/items?itemName=Wscats.search 如果你应用的是国产 Hbuider 编辑器,你能够点击这里进行下载: https://ext.dcloud.net.cn/plugin?id=3557搜寻首先,第一个最重要的性能就是搜寻,作为开发者,咱们每天打代码必定都离不开搜寻,当你在写代码的过程中遇到不明确的库,比方:require('react'),你就能够在编辑器中,选中代码中对应的关键词 react,而后点击鼠标右键,在呈现的菜单面板中抉择 Search Online 菜单项,插件会主动帮你关上默认浏览器,并搜寻对应的关键词和显示搜寻后果。 当然你还能够选中对应的关键词后,应用快捷键 cmd+enter(mac) / ctrl+enter(win) 去关上浏览器进行搜寻,这样会更高效,再也无需每次切换屏幕到浏览器,输出搜寻网址键入关键词而后进行搜寻啦。 翻译英文不好的同学的福音,当你在代码中遇到不懂的单词,你能够在编辑器中,选中代码中对应的关键词,而后点击鼠标右键,在呈现的菜单面板中抉择 Traslate Online 菜单项,插件会主动帮你关上默认浏览器,并进入谷歌翻译搜寻,搜寻对应的关键词的翻译后果。 同样你还能够选中对应的关键词后,应用快捷键 cmd+shift+enter(mac) / ctrl+shift+enter(win) 去关上浏览器进行翻译。 这里还应用了离线英汉词典插件中提供的离线词典库,所以反对了离线词典的搜寻,也是跟下面一样雷同的操作,选中代码中的关键词,翻译后果会呈现在底部栏右下角,简略的翻译无需频繁地征询百度和谷歌翻译,在底部展现后果,不便也清晰,如果你想查看更具体的翻译后果,能够点击底部栏右下角的中文翻译后果,此时会关上你的默认浏览器进行线上翻译。 切换搜索引擎如果你有其余特地须要,你能够切换不同的搜索引擎,只须要点击在编辑器底部栏右侧 Search Engine,而后在弹窗选项中抉择你须要的搜索引擎即可切换。 你还能够在右键菜单栏中抉择 Search Online By Switch Engine菜单项,间接切换对应的搜索引擎进行搜寻。 如果预设的搜索引擎地址不能满足你的应用,你能够手动更新搜索引擎地址,进入插件的 Extesion Settings 里设置即可。 默认的各搜索引擎地址格局如下: 留神:应用 %SELECTION% 来替换搜索引擎选中的关键词EngineUrlGooglehttps://www.google.com/search...Binghttps://www.bing.com/search?q...Githubhttps://www.github.com/search...Baiduhttps://www.baidu.com/search?...Npmhttps://www.npmjs.com/search?...Yahoohttps://search.yahoo.com/sear...Wikihttps://wikipedia.org/wiki/%S...Duckhttps://duckduckgo.com/?q=%SE...Code Penhttps://codepen.io/search/pen...Code Sandboxhttps://codesandbox.io/search...比方,你能够键入一个色彩网站的搜索引擎,当前打着打着代码就能够随时进入一波贤者模式了(手动滑稽)。 哼,你还能够通过批改 .vscode/setting.json 文件,来设置默认搜索引擎,例如批改 search-online.search-engine 的配置参数为 Bing,即可应用 Bing 作为默认搜索引擎来搜寻。 ...

December 2, 2020 · 1 min · jiezi

关于node.js:Nodejs学习笔记1Node基本情况

一、Node Web应用程序劣势:单线程编程模型 Q:不可能让用户干等着呀,node要怎么解决呢?A:引入事件机制1.1 非阻塞I/O面临问题:拜访磁盘和网络的I/O个别较慢用户心愿:在读取文件或通过网络发送音讯时,运行平台不会阻塞业务逻辑的执行Node解决方向:事件、异步API、非阻塞I/O 非阻塞I/O:程序能够在做其余事件的时候发动网络申请获取资源,但网络操作实现之后会运行一个回调函数来解决这个操作的后果图:一个Node应用程序中的异步非阻塞组件 1.2事件轮询event loop事件轮询是单向运行的先入先出队列,要通过几个阶段:1.计时器开始执行2.运行I/O回调3.用setImmediate安顿回调(容许将回调安顿在以后队列中的I/O回调实现之后立刻执行) 二、ES6、Node和V82.1 ES6和Node能够创立类能够应用let和const解决作用域问题原生的promise和生成器模板字符串箭头函数...... 2.2 Node和V8 2.3 应用个性组蕴含了V8提供的ES6个性,别离为:shipping、staged、in progress三组 shipping:默认开启staged:在运行Node时加上参数 --harmony(V8团队将所有靠近实现的个性都放在了这一组)in progress:倡议通过grep "in progress"来查问以后可用的in progress个性2.4 Node公布打算长期反对版(LTS)以后版每日构建版 三、Node自带的工具3.1 npm用于装置npm注册核心的包,显示和分享本人的我的项目......全局装置的包个别是工具、命令 3.2 外围模块相当于规范库 3.2.1 文件系统文件系统库fs、path 3.2.2 网络TCP客户端和服务端库(net)、HTTP库(http和https)、域名解析库(dns) 3.2.3 调试器自带的调试器反对单步执行和REPL(读取-计算-输入-循环)Node反对Chrome交互式调试 四、三种支流的Node程序4.1 Web应用程序4.2 命令行工具和后台程序JavaScript开发人员所应用的过程管理器和JavaScript转译器 4.3 桌面程序

November 23, 2020 · 1 min · jiezi

关于node.js:node使用原生方式连接mysql数据库

node应用原生形式,连贯mysql数据库(async () => { // 链接数据库 const mysql = require('mysql2/promise'); // npm i mysql2 const cfg = { host: 'localhost', user: 'root', password: ';he%0f_,ljyW', database: 'izengx', } const connection = await mysql.createConnection(cfg); // 创立一个新表tests let ret = await connection.execute(`CREATE TABLE IF NOT EXISTS tests ( id INT NOT NULL AUTO_INCREMENT, message VARCHAR(45) NULL, PRIMARY KEY (id) )`) console.log('create', ret); // 新建数据 ret = await connection.execute(`INSERT INTO tests(message) VALUE(?)`, ['newData']) console.log('新建数据', ret); const [rows, fields] = await connection.execute(` SELECT * FROM tests `) console.log('查问数据', rows); })()应用数据库中间件(ORM):sequelize连贯和操作数据库(async () => { const Sequelize = require('sequelize'); const sequelize = new Sequelize('izengx', 'root', ';he%0f_,ljyW', { host: 'localhost', dialect: 'mysql', operatorsAliases: false, }) const Fruit =sequelize.define('Fruit', { name: {type: Sequelize.STRING(20), allowNull: false,}, price: {type: Sequelize.FLOAT, allowNull: false}, stock: {type: Sequelize.INTEGER, defaultValue: 0} }) // 同步数据库 let ret = await Fruit.sync(); // 减少一条数据 ret = await Fruit.create({ name: 'banana', price: 3.5 }) console.log('create', ret);})()

November 21, 2020 · 1 min · jiezi

关于node.js:nodejs实现批量裁剪图片功能

1、初始化首先新建一个 tailor-img 文件夹,接着执行 npm init -y 初始化一个package.json 2、装置相干插件archiver 压缩文件canvas 裁剪图片glob 批量获取门路npm i archiver canvas glob --save 3、app.jsconst fs = require('fs')const { basename } = require('path')// 压缩文件const archiver = require('archiver')// canvas库,用于裁剪图片const { createCanvas, loadImage } = require('canvas')// 批量获取门路const glob = require('glob')const config = require('./config')// 依据宽高获取配置function getOptions(options, config) { const [sourceWidth, sourceHeight] = options const { width, height, isWidth, isHeight, scale } = config const haveWidth = [width, (sourceHeight * width * scale) / sourceWidth] const haveHeight = [(sourceWidth * height * scale) / sourceHeight, height] if (width === 0 || height === 0) { return [0, 0] } if (width && height) { if (isWidth) { return haveWidth } if (isHeight) { return haveHeight } return [width / scale, height / scale] } if (width && !height) { return haveWidth } if (height && !width) { return haveHeight } return options.map((item) => item / scale)}!(async () => { const paths = glob.sync('./images/*') // 压缩成zip const archive = archiver('zip', { zlib: { level: 9, }, }) // 输入到以后文件夹下的 image-resize.zip const output = fs.createWriteStream(__dirname + '/image-resize.zip') archive.pipe(output) for (let i = 0; i < paths.length; i++) { const path = paths[i] const image = await loadImage(path) const { width, height } = image // 因为应用了扩大运算符开展对象,这里须要为对象定义迭代器 const obj = { width, height } obj[Symbol.iterator] = function () { return { next: function () { let objArr = Reflect.ownKeys(obj) if (this.index < objArr.length - 1) { let key = objArr[this.index] this.index++ return { value: obj[key] } } else { return { done: true } } }, index: 0, } } // 默认缩放2倍 // const options = [width, height].map((item) => item / 2) const options = getOptions(obj, config) const canvas = createCanvas(...options) const ctx = canvas.getContext('2d') ctx.drawImage(image, 0, 0, ...options) archive.append(canvas.toBuffer(), { name: `${basename(path)}` }) }})()4、config.js用于批改宽低等配置module.exports = { width: 300, height: '', // 依据宽度等比缩放,优先级更高 isWidth: true, // 依据高度等比缩放 isHeight: false, // 宽高整体缩放 scale: 1,}

November 20, 2020 · 2 min · jiezi

关于node.js:爬虫spider

const originRequest = require('request');const cheerio = require('cheerio');const iconv = require('iconv-lite');const request = (url, cb ) => { const options = { url: url, encoding: null }; originRequest(url, options, cb);}for (let i=1; i< 10; i++) { const url = `https://www.gdnync.com/news/snzx/list_1_${i}.html`; request(url, (err, res, body) => { const html = iconv.decode(body, 'gb2312'); const $ = cheerio.load(html); const list = $('.list-group-item'); for (let i=0,len=list.length; i<len; i++) { let title = list.eq(i).find('.nc-subcolumn-list-item-title').text(); console.log(title); } })}

November 19, 2020 · 1 min · jiezi

关于node.js:实现一个简单的websocket

实现简略的websocket,只须要几步: 引入socket.io组件;前端初始化页面时,监听socket.on('chatMsg', () => xxx);须要发送事件时,触发socket.emit('chatMsg', 'msg');后端监听事件并回调即可index.html<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title></head><body> <div id="app"> <input type="text" id="name"> <button type="button" @click="submit">send</button> <ul v-for="(item, i) in msgList" :key="item + new Date().getTime()"> <li>{{i+1}}.{{item}}</li> </ul> </div> <script src="https://cdn.bootcdn.net/ajax/libs/axios/0.21.0/axios.js"></script> <script src="https://lib.baomitu.com/vue/2.6.12/vue.js"></script> <script src="https://lib.baomitu.com/socket.io/3.0.1/socket.io.js"></script> <script> // 生成对象 let socket = io(); let vm = new Vue({ el: '#app', data: { msgList: [], }, created () { // 监听 socket.on('chatMsg', (msg) => { vm.msgList.push(msg) }) }, methods: { submit: async () => { let msg = document.getElementById('name').value; document.getElementById('name').value = ''; // 发送事件 socket.emit('chatMsg', msg); }, } }) </script></body></html>index.jsconst express = require('express');const app = express();const http = require('http').Server(app);const io = require('socket.io')(http);app.get('/', (req, res) => { res.sendFile(__dirname + '/index.html');})// 监听io.on('connection', (socket) => { console.log('a socket connection....'); // 事件达到时 socket.on('chatMsg', (msg) => { io.emit('chatMsg', msg); }) // 链接断开时 socket.on('disconnect', () => { console.log('disconnect'); })})http.listen(3000, () => { console.log('http listen 3000............');})

November 19, 2020 · 1 min · jiezi

关于node.js:启动一个node后台服务

应用koa创立的形式入口index.html<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title></head><body> <form action="/add" method="POST"> <input type="text" name="key1"> <input type="submit" value="Add"> </form> <script src="https://cdn.bootcdn.net/ajax/libs/axios/0.21.0/axios.js"></script> <script> (async () => { const res2 = await axios.post('/api/users', { key: 'value', }); document.writeln(`RES : ${JSON.stringify(res2.data)}`) })() </script></body></html>index.jsconst Koa = require('koa');const app = new Koa();const router = require('koa-router')();const bodyParser = require('koa-bodyparser'); // 解决form表白提交的数据格式app.use(require('koa-static')(__dirname + '/')); // 引入index.html文件app.use(bodyParser());router.post('/add', async (ctx, next) => { console.log('body', ctx.request.body) ctx.body='这是post申请';})router.get('/add', async (ctx, next) => { console.log('get'); ctx.body='这是get申请';})router.post('/api/users', async (ctx, next) => { console.log('get'); ctx.body='这是get申请, /api/users';})app.use(router.routes())app.listen(3000)应用http的形式创立蕴含跨域的申请index.html<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title></head><body> <script src="https://cdn.bootcdn.net/ajax/libs/axios/0.21.0/axios.js"></script> <script> (async () => { axios.defaults.baseURL = 'http://localhost:4000'; axios.defaults.withCredentials = true const res2 = await axios.post('/api/users', { key: 'value', }); document.writeln(`RES : ${JSON.stringify(res2.data)}`) })() </script></body></html>index.jsconst api = require('./api');const proxy = require('./proxy');api.listen(4000);proxy.listen(3000);proxy.jsconst express = require('express');const {createProxyMiddleware} = require('http-proxy-middleware');const app = express();app.use(express.static(__dirname + '/'));app.use('/api', createProxyMiddleware({ target: 'http://localhost:4000', changeOrigin: false,}))module.exports = app;api.jsconst http = require('http');const fs = require('fs');const app = http.createServer((req, res) => { const {url, method, headers} = req; if (url === '/' && method === 'GET') { fs.readFile('index.html', (err, data) => { if (err) { res.writeHead(500, {'Content-Type': 'text/plain'}); res.end('服务器谬误') } res.writeHead(200, {'Content-Type': 'text/html'}) res.end(data) }) } else if ((method === 'GET' || method === 'POST') && url === '/api/users') { res.setHeader('Access-Control-Allow-Origin', 'http://localhost:3000') res.setHeader('Access-Control-Allow-Credentials', 'true') res.setHeader('Set-Cookie', 'cookie=val12123') res.setHeader('Content-Type', 'application/json'); res.end(JSON.stringify([{name: 'tom'}])) } else if (method === 'OPTIONS' && url === '/api/users') { res.setHeader('Access-Control-Allow-Credentials', 'true') res.writeHead(200, { 'Access-Control-Allow-Origin' : 'http://localhost:3000', 'Access-Control-Allow-Headers' : 'X-Token,Content-Type', 'Access-Control-Allow-Methods' : 'PUT', }) res.end() }})module.exports = app;

November 19, 2020 · 2 min · jiezi

关于node.js:使用-jszip-实现文件打包下载

背景通过程序主动生成了jsx和css文件,咱们须要将它们下载下来拿到别的我的项目中去应用,单个下载很麻烦,因而咱们将这些文件打成zip包,间接解压放到已有我的项目即可。以前这种下载都是后端同学提供反对,或者给到数据,在前端本人拼接数据生成zip包,这种需要还是第一次做开发。通过一系列的尝试的,最初应用 jszip 来实现。 node server端实现代码const fs = require('fs');const path = require('path');const JSZip = require('jszip');const jsxPath = path.join(__dirname, '../output/taro.jsx');const cssPath = path.join(__dirname, '../output/index.less');router.get('/download', (req, res) => { res.setHeader('Content-Type', 'application/zip'); const zip = new JSZip(); // 申明一个压缩文件夹 const folder = zip.folder("code");     // 为文件夹增加文件 // 如果是须要压缩一个目录下文件夹,那么循环以后这个文件夹, // 为文件夹挨个增加文件名以及文件内容 folder.file('taro.jsx', fs.readFileSync(jsxPath)); folder.file('index.less', fs.readFileSync(cssPath)); // 通过 base64 类型生成zip的内容 zip.generateAsync({type: 'base64'}) .then(content => { res.status(200).send(content); });});client 端实现handleDownload = async () => { // 与server交互应用封装的 axios const { data } = await http('/download'); const zip = new JSZip(); // 获取到的数据应用 base64 加载 await zip.loadAsync(data, { base64: true }); // 生成blob模式的文件 const blob = await zip.generateAsync({ type: 'blob' }); const url = window.URL.createObjectURL(blob); // 惯例下载操作 const link = document.createElement('a'); link.setAttribute('href', url); link.setAttribute('download', 'code.zip'); document.body.appendChild(link); link.click(); link.remove();}总结小小的一个性能,捣鼓了半下午,依照本人原来想法,间接应用node生成zip文件,而后应用res.download(filepath)扔出去,后果下载之后解压,始终提醒格局谬误,导致消耗了很多工夫去解决这个问题,看到有提醒应用原生xmlhttprequest,并没有解决带来的问题。明天算是瞎鼓捣了,也胜利了,记录一下吧。 ...

November 17, 2020 · 1 min · jiezi