- 假如第一版已经上线运行,第二版要发布,重启服务的话不就断掉啦?是不是至少部署两台机器,然后用nginx去转发一下?有没有大神能提供一些实现细节
- 单元测试是必写的吗?
- https://github.com/papertiger8848/modelproxy类似这种的轻量级的接口配置建模框架,在eggjs里有没有更好的
【部署上线】eggjs服务的疑问
CEAMS: 基于Node.js的高效微服务应用开发运维和API管理系统提供免费下载使用
通用企业应用接口管理系统(Common Enterprise Application interface Management System)为用户提供基于Node.js的云端微服务应用开发运维,以及API管理解决方案。
CEAMS为云端微服务应用提供基于浏览器的在线一体化开发、调试、部署、监控管理、访问认证等能力。用户可在CEAMS系统上使用大量方便的云端服务应用的自动化开发和管理功能,例如自动化测试工具、代码和文档生成,零中断时间的一键升级和回滚应用版本,应用代码下载上传、版本比较等方便的功能。
CEAMS系统由系统管理终端、应用开发管理网站及门户、以及高性能应用服务器三部分组成。系统为用户提供基于网页的统一在线应用门户中心,用户可在其中查看系统中部署的各类在线应用,同时提供对应用的分类和检索能力。CEAMS系统提供在线测试、浏览API文档、自动生成调用方接入代码等方便功能。
统一的应用展示中心,用户可从中添加自己需要的服务资源:
自动生成清晰严谨API文档和API接入端代码,支持基于JSON Schema的数据校验:
为方便开发,CEAMS系统为用户的云端应用提供统一的API规范,以及基于该规范的HTTP + JSON的API调用接口,可支持各类客户端,例如移动端app,企业后台应用等类型应用的接入。开发云端应用时,用户首先在平台上编辑并生成应用的API规范。CEAMS系统为云端微服务应用提供的统一API规范借鉴了部分UPnP规范的设计,可被看成是一个JSON版的WSDL规范。基于该API规范,平台为应用提供各项方便的自动化能力,例如API文档、客户端接入代码自动生成、应用框架代码自动生成、基于JSON schema的严格数据校验能力、基于JSON schema form表单自动生成的API测试工具、灵活的API数据缓存和限流保护等能力。
基于JSON Schema form自动输入表单生成能力的API测试工具:
在CEAMS系统中,每个应用是一个标准的NPM包,可以对其添加任意开源第三方NPM依赖。在API规范编辑完成后,系统将自动为应用生成应用的框架代码,包含一个NPM包所需要的所有基础文件,以及API实现函数的入口等,开发者只需要编写函数的实现部分代码即可完成开发,而无需关心繁琐的HTTP协议实现,传参方法等。
系统为开发者提供了基于Web IDE的线上开发环境,可支持多用户同时在线开发。用户可以在在浏览器中,线上完成应用的开发、调试、和部署,而无需重复代码在本地开发测试,线上部署的繁琐过程。得益于CDIF应用服务器提供的热更新能力,应用从启动调试到完成部署仅需数十秒即可完成。同时,系统也支持在VSCode等流行的IDE中完成应用的线下开发调试,并通过NPM压缩包格式一键上传到系统中并部署。
基于浏览器的云端开发环境,支持多人同时在线开发调试,Web Terminal和Node.js REPL:
系统提供完整的Node.js NPM生态支持(https://www.npmjs.com),用户可自由引用NPM生态中70多万个各类开源包中的任意一个,例如各类工具库、数据库驱动,消息中间件接口等,帮助方便地开发其云端应用和对接到各类异构系统资源。为方便使用,CEAMS系统为用户提供了免费的国内高速NPM镜像,内置了常用的数千个NPM包资源,并可实时自动更新版本和添加更多第三方开源NPM包。同时,系统内置了对各类常用协议,例如对REST API、SOAP等的支持,可帮助应用开发者方便地连接并从其他系统获取应用开发需要的数据和能力。
CEAMS系统已支持Node.js最新版本带来的多线程能力。在多线程模式下,每个应用部署于独立的worker线程中,并具备单独的线程上下文和堆空间,执行高CPU占用率任务时不会阻塞其他应用的执行。同时适用于I/O密集型与CPU密集型任务,如API网关和数据计算处理等。CEAMS系统的应用服务器可无缝地随时在传统的单线程和新的多线程模式下切换,对已部署的应用毫无感知。
应用服务器同时提供Node.js单线程和多线程运行模式,并可指定扩容实例个数:
更进一步,基于CDIF应用服务器为应用提供的统一JSON数据接口,在获得相应的应用访问权限后,用户可使用纯粹JSON 数据格式调用系统中部署的其他应用,灵活地组织和处理来自不同应用的JSON 数据,并使用lodash、JSON path等高效的数据转换和查询工具,配合async等异步并发流程控制组件,组织出复杂、高性能的组合微服务应用逻辑和工作流程场景。
为帮助用户使用,CEAMS系统封装了Node.js多线程API,为不同应用线程之间的数据相互调用提供了高性能的异步消息接口,并且在单线程模式和多线程模式下完全统一。用户无需理解和使用繁杂的Node.js多线程API,或基于Cluster的多进程模型。只需要在应用的任何位置添加几行代码,创建对任意服务应用的客户端对象,并根据该服务应用提供的JSON API规范,即可完成和该服务应用之间的数据对接。
CEAMS系统已被成功应用于国内省级警务云平台建设,以及其他多个政企项目中,并稳定运行至今。我们在期间从未收到过一次故障崩溃报告。
目前,我们已为CEAMS系统已提供社区版免费下载,社区版包含了系统的全部功能,可以满足中小规模应用场景。用户可以通过bash安装脚本,在常用的Linux操作系统上一键下载、安装和启动整个系统。以下是CEAMS产品的下载连接,其中包含了系统的下载安装方法、用户手册、开发指南等文档:
如果您对CEAMS系统的使用有任何问题,欢迎您邮件至:support@apemesh.com,或者加入灵长科技技术支持QQ群:618450152 向我们询问和了解。
nodejs的api这么多,在学习的过程中应该如何有的放矢。
用过express写过两个很小的项目,但是对于nodejs本身了解的很少。每次想要好好的学习下nodejs,然而点开文档,随便找一个模块都发现api这么多。 在这么多的api当中,如何选择最常用的。
2019年5月更新TypeScript入门实战教程-类 接口 泛型 泛型类 ts封装类似Mongoose的db库、装饰器-免费分享
ts是前端必备技能,此教程类 接口 泛型 泛型类、模块、装饰器都讲了,算是市面上最全的ts教程。 废话不多说 直接上地址。
2019年5月更新TypeScript入门实战教程B站地址:
https://www.bilibili.com/video/av38379328/?p=1
2019年5月更新TypeScript入门实战教程百度网盘地址:
朋友们能分享一下nodejs入门教程吗
突然想入坑nodejs了 求推荐入坑教程
node如何 response byte 数据
原数据( json ):{"id":1010,"na":"zhangsan"}
转成 byte:[123 34 105 100 34 58 49 48 49 48 44 34 110 97 109 101 34 58 34 229 188 160 228 184 137 34 125]
现在想直接通过 http 的方式将 byte send 出去,好像不行啊? 用 golang 和 node.js 分别试了下,最后 send 出去的文件打开之后就直接变成了原 json 串了
付代码:
let b = new Buffer(`{"id":1010,"na":"zhangsan"}`)
response.send(b)
express传入模板引擎变量的源码分析
express中为模板传入变量的时候可以通过: 1.res.render的options: 通过向res.render函数传入optinos:res.render(目标模板名,{user:‘djw’});
在EJS模版中通过<%=user%>使用变量
2.res.locals: 在res.locas对象上直接赋值:res.locals.user = ‘djw’
3.app.locals 在res.locas对象上直接赋值:res.locals.user = ‘djw’
4.app.set 通过向app.set函数传入变量名称和值:app.set(‘user’,‘djw’);这种方式会向模板中传入一个程序级变量Settings,在EJS模板中通过<%=settings.user%>使用变量
res.render的opts 、res.locals、app.locals的优先级: 由于通过app.set设置的变量其实只挂在app.locals.settings上面的,所以不用考虑优先级设置。
为什么是这种优先级呢? 在调用res.render中会先把res.locals挂到res.render的options上①,然后调用app.render②:
res.render = function render(view, options, callback) { var app = this.req.app; var done = callback; var opts = options || {}; var req = this.req; var self = this;
// support callback function as second arg if (typeof options === ‘function’) { done = options; opts = {}; }
// merge res.locals opts._locals = self.locals; ①
// default callback to respond done = done || function (err, str) { if (err) return req.next(err); self.send(str); };
// render app.render(view, opts, done); ② };
在app.render创建renderOptions然后依次把app.locals,res.locals,res.render的optionsmerge到renderOptions上。
先看下merge的实现:
exports = module.exports = function(a, b){ if (a && b) { for (var key in b) { a[key] = b[key]; } } return a; }; merge把b上的属性赋值到a上,所以后merge的会覆盖之前已存在的属性,例如:app.locals.user=‘djw’会先merge到renderOptions上,之后res.locals.user=‘kkp’会后覆盖掉已存在的user。这样就形成了res.render的options>res.locals>app.locals的优先级。
源码:
app.render = function render(name, options, callback) {
var cache = this.cache; var done = callback; var engines = this.engines; var opts = options; var renderOptions = {}; var view;
// support callback function as second arg if (typeof options === ‘function’) { done = options; opts = {}; }
// merge app.locals merge(renderOptions, this.locals);
// merge options._locals options._locals就是挂在的render的options上的res.locals if (opts._locals) { merge(renderOptions, opts._locals); }
// merge options merge(renderOptions, opts);
// set .cache unless explicitly provided if (renderOptions.cache == null) { renderOptions.cache = this.enabled(‘view cache’); }
// primed cache if (renderOptions.cache) { view = cache[name]; }
// view if (!view) { var View = this.get(‘view’);
view = new View(name, { defaultEngine: this.get(‘view engine’), root: this.get(‘views’), engines: engines });
if (!view.path) { var dirs = Array.isArray(view.root) && view.root.length > 1 ? ‘directories "’ + view.root.slice(0, -1).join(’", “’) + '” or “’ + view.root[view.root.length - 1] + '”’ : ‘directory "’ + view.root + '"' var err = new Error(‘Failed to lookup view "’ + name + '" in views ’ + dirs); err.view = view; return done(err); }
// prime the cache if (renderOptions.cache) { cache[name] = view; } }
// render tryRender(view, renderOptions, done); }; 之后tryRender通过app.set(‘view’,fn)设置的模板引擎进行渲染。 掘金连接:https://juejin.im/post/5cd0f948e51d456e2d69a828引用:
1.《node.js实战》图片
2.express.源码
cnode這個論壇只用了一台服務器嗎
RT
不是说 Node 12 又快很多了吗,这是错觉?
测试代码
const http = require("http");
const fs = require("fs");
const path = require("path");
const port = 3000;
function sleep(ms) {
return new Promise(resolve => {
setTimeout(() => {
resolve();
}, ms);
});
}
http
.createServer(async function(request, response) {
await sleep(200);
response.end("Hello, world!");
})
.listen(port);
console.log(`listen http://localhost:${port}/`);
Node v10.15.3
> siege -c 100 -t 10s http://127.0.0.1:3000/
Transactions: 4193 hits
Availability: 100.00 %
Elapsed time: 9.83 secs
Data transferred: 0.05 MB
Response time: 0.23 secs
Transaction rate: 426.55 trans/sec
Throughput: 0.01 MB/sec
Concurrency: 98.04
Successful transactions: 4200
Failed transactions: 0
Longest transaction: 0.26
Shortest transaction: 0.20
Node v12.0.0
> siege -c 100 -t 10s http://127.0.0.1:3000/
Transactions: 3809 hits
Availability: 100.00 %
Elapsed time: 9.10 secs
Data transferred: 0.05 MB
Response time: 0.23 secs
Transaction rate: 418.57 trans/sec
Throughput: 0.01 MB/sec
Concurrency: 96.55
Successful transactions: 3809
Failed transactions: 0
Longest transaction: 0.26
Shortest transaction: 0.20
【北京】北京光合信诚科技有限公司招聘node.js开发工程师
【关于我们】 北京光合信诚科技有限公司是一家致力于用安全技术赋能区块链,探索 数字资产安全技术解决方案的初创科技公司。 光合信诚实力雄厚,成立两个月获得启赋资本等投资机构的700万天使轮投资。目前已取得多项国内、国际专利,拥有完全自主知识产权的智能卡钱包操作系统。光合信诚先后开发了硬件钱包—币盾、软硬件结合手机钱包—BiMoney等产品,产品上线即获关注。 光合信诚以硬件安全技术为基础,提供从硬件到软件,从个人到企业的全方位的数字资产安全技术解决方案,在数字资产存储、托管、支付、交易、理财等应用场景下有很大发挥空间。 BiMoney &币盾 是光合信诚基于COS(金融智能IC芯片的卡COS操作系统开发)和区块链技术 进行数字资产安全技术研究的项目。 数字资产持有人群迅速扩张,数字资产总额讯速扩大,对数字资产安全技术要求也相应提高,而目前行业内缺少真正安全易用的硬件钱包(硬件数字资产安全产品)。 光合信诚基于此开发出了币盾以及BiMoney,币盾是一款硬件钱包,BiMoney是以币盾为基础软硬结合的手机钱包。币盾使用自主研发的金融级芯片,技术获得EMVCo、CCEAL4双重认定,抵御电子探测攻击能力领先世界。币盾结合区块链技术内建封闭完备的智能卡安全操作系统BtxOS,为密钥存储和数据签名提供可信执行环境;在防伪交易方面,币盾采用双端分离技术,保证保证交易的安全。BiMoney手机钱包软硬技术结合,固件密封性良好,并已通过IP67防水防尘认证;BiMoney在 -40—125度都可以保持存储正常;BiMoney APP兼备BTC、ETH、RRC等20多种主流数字货币,业内领先。
【薪酬范围】20k~25k 【简历接收邮箱】yan.peng@btxon.com 【工作地点】北京市海淀区海淀南路19号时代网络大厦 近十号线苏州街站 【岗位职责】 1、参与产品后端功能的设计与研发,及持续重构; 2、完成基于nodejs/redis/postgres等技术的服务器端API开发,使之能支撑千万用户级的移动应用; 3、完成基于javascript引擎技术栈的前端功能逻辑和UI 4、负责基于docker的产品的部署,上线后的维护和优化。 【任职要求】 1、两年以上开发工程师经验,对Node.js以及其他新技术充满热情; 2、熟练掌握Javascript语言编程,熟悉Node.js标准库的使用,能完成相应的扩展开发; 3、具备express、promise、async等框架的使用经验,熟悉HTTP,TCP/IP网络协议,熟悉Restful API 设计; 4、精通MySQL等关系型数据库应用系统设计及优化熟悉linux,熟悉存储引擎及存储过程, 熟悉数据库部署和调优; 5、精通 Redis,熟悉和掌握源代码管理软件(GIT优先); 6、具有Linux上的开发经验,能够编写常用和基本的Shell脚本; 7、高度的责任心以及良好团队合作精神,有高并发后端开发和海量数据处理经验; 8、有NoSQL项目开发经验,有敏捷或流行软件开发流程的经验; 9、对算法有良好的理解能力、深入理解面向对象及设计模式思想; 10、良好的文档书写能力和代码注释习惯,对代码整洁度、可维护性有较高追求;
灵异事件--文件夹消失了
一个其他部门的同事(用mac一体机)在使用我开发的小工具(electron开发)的时候,有几个桌面的文件夹和文件莫名消失,各种地方都找了,连痕迹都没有,正在尝试恢复误删文件数据,其他人没出现这种情况,这个锅我不能背啊。求助mac大神
最简洁的react router,仅一行代码。
掌握 Async/Await
摘要:还不用Async/Await就OUT了。。
- 原文:掌握 Async/Await
- 作者:Jartto
Fundebug经授权转载,版权归原作者所有。
前端工程师肯定都经历过 JS 回调链狱的痛苦过程,我们在使用 Promise 的时候总是不尽人意。这时候 Async/Await 应运而生,它到底有什么魔力,我们来说道说道。
一、回顾 Promise
所谓 Promise,简单说就是一个容器,里面保存着某个未来才会结束的事件(通常是一个异步操作)的结果。
1. 语法
new Promise(executor);
new Promise(function(resolve, reject) { ... });
2. 参数
带有 resolve 、reject 两个参数的一个函数。这个函数在创建 Promise 对象的时候会立即得到执行(在 Promise 构造函数返回 Promise 对象之前就会被执行),并把成功回调函数(resolve)和失败回调函数(reject)作为参数传递进来。调用成功回调函数(resolve)和失败回调函数(reject)会分别触发 Promise 的成功或失败。
这个函数通常被用来执行一些异步操作,操作完成以后可以选择调用成功回调函数(resolve)来触发 Promise 的成功状态,或者,在出现错误的时候调用失败回调函数(reject)来触发 Promise 的失败。
3. Promise.all
用 Promise.all来执行,all接收一个数组参数,里面的值最终都算返回 Promise对象。这样,三个异步操作的并行执行的,等到它们都执行完后才会进到 then里面。
Promise.all([async1(), async2(), async3()])
.then(function(results){
console.log(results);
});
all会把所有异步操作的结果放进一个数组中传给 then,就是上面的 results。
4. Promise.race
all方法的效果实际上是「谁跑的慢,以谁为准执行回调」,那么相对的就有另一个方法「谁跑的快,以谁为准执行回调」,这就是 race方法:
Promise.race([requestImg(), timeout()])
.then(function(results){
console.log(results);
})
.catch(function(reason){
console.log(reason);
});
上述代码演示了 race的基本用法,实现的功能是:请求图片,如果请求成功就返回图片,否则就调用超时函数。
更多资源,请查看:
二、Promise 为何不完美?
乍一看,Promise还不错,帮我们解决了回调链狱的问题。当然这只是简单使用,碰到复杂的业务也有很鸡肋的场景,比如:
1. 错误处理
在下面的 Promise示例中,Try/Catch不能处理 JSON.parse的错误,因为它在 Promise中。我们需要使用 catch,这样错误处理代码非常冗余。并且,在我们的实际生产代码会更加复杂。
const makeRequest = () => {
try {
getJSON().then(result => {
// JSON.parse可能会出错
const data = JSON.parse(result)
console.log(data)
})
// 取消注释,处理异步代码的错误
// .catch((err) => {
// console.log(err)
// })
} catch (err) {
console.log(err)
}
}
Async/Await让 Try/Catch可以同时处理同步和异步错误。使用 Async/Await的话,Catch能处理 JSON.parse错误:
const makeRequest = async () => {
try {
// this parse may fail
const data = JSON.parse(await getJSON())
console.log(data)
} catch (err) {
console.log(err)
}
}
Async/Await最让人舒服的一点是代码看起来是同步的。
2. 条件语句
下面示例中,需要获取数据,然后根据返回数据决定是直接返回,还是继续获取更多的数据。
const makeRequest = () => {
return getJSON()
.then(data => {
if (data.needsAnotherRequest) {
return makeAnotherRequest(data)
.then(moreData => {
console.log(moreData)
return moreData
})
} else {
console.log(data)
return data
}
})
}
这些代码看着就头痛。嵌套(6层),括号,return语句很容易让人感到迷茫,而它们只是需要将最终结果传递到最外层的Promise。如果换成 Async/Await呢:
const makeRequest = async () => {
const data = await getJSON();
if (data.needsAnotherRequest) {
const moreData = await makeAnotherRequest(data);
console.log(moreData);
return moreData;
} else {
console.log(data);
return data;
}
}
所以,这才是真正摆脱回调链狱的正确做法。
3. 中间值
你很可能遇到过这样的场景,调用 promise1,使用 promise1返回的结果去调用 promise2,然后使用两者的结果去调用promise3。你的代码很可能是这样的:
const makeRequest = () => {
return promise1()
.then(value1 => {
return promise2(value1);
.then(value2 => {
return promise3(value1, value2);
})
})
}
// 或者:
const makeRequest = () => {
return promise1()
.then(value1 => {
return Promise.all([value1, promise2(value1)])
})
.then(([value1, value2]) => {
return promise3(value1, value2)
})
}
怎么写都会觉得很复杂,那如果 Async/Await用来实现呢,表现可能如下:
const makeRequest = async () => {
const value1 = await promise1();
const value2 = await promise2(value1);
return promise3(value1, value2);
}
是不是很 6 ,将复杂的场景简化,这样的代码就很有灵性了。
4. 错误栈
调用了多个 Promise,假设 Promise链中某个地方抛出了一个错误,Promise链中返回的错误栈没有给出错误发生位置的线索。更糟糕的是,它会误导我们;错误栈中唯一的函数名为 callAPromise,然而它和错误没有关系。(文件名和行号还是有用的)。
const makeRequest = () => {
return callAPromise()
.then(() => callAPromise())
.then(() => callAPromise())
.then(() => callAPromise())
.then(() => callAPromise())
.then(() => {
throw new Error("oops");
})
}
makeRequest().catch(err => {
console.log(err);
// output
// Error: oops at callAPromise.then.then.then.then.then (index.js:8:13)
})
然而,Async/Await中的错误栈会指向错误所在的函数:
const makeRequest = async () => {
await callAPromise();
await callAPromise();
await callAPromise();
throw new Error("oops");
}
makeRequest().catch(err => {
console.log(err);
// output
// Error: oops at makeRequest (index.js:7:9)
})
5. 调试
调试 Promise有两个问题:
- 不能在返回表达式的箭头函数中设置断点;
- 如果你在
then代码块中设置断点,调试器不会跳到下一个then,因为它只会跳过异步代码;
而使用 Await/Async时,你不再需要那么多箭头函数,这样你就可以像调试同步代码一样跳过 Await语句。
这里只简单的列出问题,详细请查看原文:Async/Await 替代 Promise 的 6 个理由
三、新时代的曙光 Async/Await
简单介绍:
- Await/Async 是写异步代码的新方式,以前的方法有回调函数和 Promise。
- Await/Async 是基于 Promise 实现的,它不能用于普通的回调函数。
- Await/Async 与 Promise 一样,是非阻塞的。
- Await/Async 使得异步代码看起来像同步代码,这正是它的魔力所在。
使用 Promise是这样的:
const jarttoDemo = () =>
getJSON().then(data => {
return data;
})
jarttoDemo();
使用 Async/Await是这样的:
const jarttoDemo = async () => {
let data = await getJSON();
return data;
}
jarttoDemo();
基本规则:
- Async 表示这是一个 Async 函数,Await 只能用在这个函数里面。
- Await 表示在这里等待 Promise返回结果了,再继续执行。
- Await 后面跟着的应该是一个 Promise 对象,当然,其他返回值也没关系,只是会立即执行,不过那样就没有意义了。
四、更多用法示例
1. 简单示例
var sleep = function (time) {
return new Promise(function (resolve, reject) {
setTimeout(function () {
resolve();
}, time);
})
};
var start = async function () {
// 在这里使用起来就像同步代码那样直观
console.log('start');
await sleep(3000);
console.log('end');
};
start();
2. 获得返回值
var sleep = function (time) {
return new Promise(function (resolve, reject) {
setTimeout(function () {
// 返回 ‘ok’
resolve('ok');
}, time);
})
};
var start = async function () {
let result = await sleep(3000);
console.log(result); // 收到 ‘ok’
};
3. 错误捕获
const makeRequest = async () => {
try {
// this parse may fail
const data = JSON.parse(await getJSON())
console.log(data)
} catch (err) {
console.log(err)
}
}
既然 then不用写了,那么 catch也不用写,可以直接用标准的 try catch语法捕捉错误。
var sleep = function (time) {
return new Promise(function (resolve, reject) {
setTimeout(function () {
// 模拟出错了,返回 ‘error’
reject('error');
}, time);
})
};
var start = async function () {
try {
console.log('start');
await sleep(3000); // 这里得到了一个返回错误
// 所以以下代码不会被执行了
console.log('end');
} catch (err) {
console.log(err); // 这里捕捉到错误 `error`
}
};
4. 条件语句
Promise写法:
const makeRequest = () => {
return getJSON()
.then(data => {
if (data.needsAnotherRequest) {
return makeAnotherRequest(data)
.then(moreData => {
return moreData;
})
} else {
return data;
}
})
}
Async/Await写法:
const makeRequest = async () => {
const data = await getJSON();
if (data.needsAnotherRequest) {
const moreData = await makeAnotherRequest(data);
return moreData;
} else {
return data;
}
}
5. 循环多个 Await
var start = async function () {
for (let i = 1; i <= 10; i++) {
console.log(`当前是第 ${i} 次等待..`);
await sleep(1000);
}
};
需要注意的是,Await必须在 Async函数的上下文中的。
6. 在 forEach中使用
async function printFiles () {
const files = await getFilePaths();
for (let file of files) {
const contents = await fs.readFile(file, 'utf8');
console.log(contents);
}
}
async function printFiles () {
const files = await getFilePaths();
await Promise.all(files.map(async (file) => {
const contents = await fs.readFile(file, 'utf8')
console.log(contents)
}));
}
示例参考如下文章:
五、总结
我们一直在强调代码的可读性和可维护性,对我来说,Async/Await 更加易懂和易用。所以,不管是 Promise 还是 Async/Await ,能解决实际问题的技术就是好技术。
当然,Async/Await 也是基于 Promise 概念的,技术上我们也可以求同存异,不必太过较真。一句话,选择权在你!
jquery + node 使用 CORS 实现跨域访问,支持cookie和自定义header
跨域有多种方式,现在的情况看来还是CORS更适合一些,有很多优点,比如浏览器正式支持、支持post、可以控制跨域访问的网站等。
我们来看看node如何实现cors方式的跨域。在网上找到了一些代码,考过来之后运行报错,可能这个是在express里面的写法吧,那么原生的写法是什么样子的呢?又找了半天,并且经过测试得到了原生的写法: express的写法:
—app.js— app.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”); res.header(“Access-Control-Allow-Methods”,“PUT,POST,GET,DELETE,OPTIONS”); res.header(“X-Powered-By”,’ 3.2.1’) if(req.method==“OPTIONS”) res.send(200);/让options请求快速返回/ else next(); });
node原生写法:
var http = require(“http”); http.createServer(function (req, res) { var a={ “a1”:“www” };
// 获得客户端的Cookie var Cookies = {}; req.headers.cookie && req.headers.cookie.split(';').forEach(function( Cookie ) { var parts = Cookie.split('='); Cookies[ parts[ 0 ].trim() ] = ( parts[ 1 ] || '' ).trim(); }); console.log(Cookies); //获取自定义头 console.log(req.headers.xtoken); // 向客户端设置一个Cookie res.setHeader('Set-Cookie','myCookie2=test'); //res.setHeader("Access-Control-Allow-Origin", "*"); res.setHeader("Access-Control-Allow-Origin", "http://127.0.0.1:8050"); //带cookie的话,不能写* res.setHeader("Access-Control-Allow-Credentials", true); //允许带 cookie res.setHeader("Access-Control-Allow-Headers", "Content-Type,Content-Length, Authorization, Accept,X-Requested-With,xToken"); res.setHeader("Access-Control-Allow-Methods","PUT,POST,GET,DELETE,OPTIONS"); res.setHeader("X-Powered-By",' 3.2.1'); res.writeHeader(200, {'Content-Type': 'application/json'}); if(req.method=="OPTIONS"){ /*让options请求快速返回*/ res.end(); } else { res.write(JSON.stringify(a)); res.end(); } }}).listen(8080);
需要先用 setHeader 进行设置,最后再用 writeHeader 进行设置。这样就可以了。 还有一些小地方,设置不好的话很容易报错。翻来覆去调试了好久才好。 然后就是客户端的写法了,由于客户端使用的框架不同,设置方式也有点差别,这里先介绍一下比较基本的jQuery的方式。
$.ajax({ type: "POST", //post方式 dataType: "JSON", //json格式的数据 cache: false, //客户端不缓存 headers: { //自定义头 xtoken: "1234qwert" }, xhrFields: { //允许跨域访问时添加cookie withCredentials: true //true "Access-Control-Allow-Origin" 不能写* ;false可以写 * }, crossDomain: true, url: "http://127.0.0.1:8080/1234", data: {"a":"11"}, //json格式的数据 //timeout: 2000, error: function (request, textStatus, errorThrown) { //访问失败,自动停止加载动画,并且给出提示 alert("提交的时候发生错误!"); }, success: function (data) { $("#div").html(data.a1); } });
这里的 xhrFields 设置,折腾半天,找了好久终于搞定了。其实只需要在后端加一行代码就行。 另外用了自定义头,客户端会自动发起两次请求。就是说你的代码之ajax了一次,但是浏览器会发起两个请求,后端会收到两个请求,所以有了 if(req.method==“OPTIONS”) res.send(200); 这样的判断。
参考目录 1、node的原生 header: https://www.cnblogs.com/jay–zhang/p/6229139.html
2、node 接收 自定义 header 作者:zding92 来源:CSDN 原文:https://blog.csdn.net/u011481543/article/details/79582555
3、node 操作cookie http://www.cnblogs.com/rubylouvre/archive/2012/08/19/2645644.html
ps:第一次在这里分享。不知道这样的分享有没有用。
讨论个有关模块化设计的问题
场景:
现在的程序中有两个模块,模块A 和 模块B。 由于业务逻辑的特殊性,B中有一个子模块C,C中有一个子模块D,D模块的初始化/构造函数依赖于外部的A模块中的一个值。除此之外, B模块中的任何方法、属性 都与A模块无任何关联。 B模块的初始化过程中会初始化子模块C,C模块的初始化过程中会初始化子模块D。
问题:
基于以上的情况:
- 该如何设计当前的模块结构才是最合适的呢?
- 鉴于模块化“高内聚低耦合”的设计原则,A和B两个模块 除了 子模块D依赖A中的一个值这一点之外,没有任何交集
- 如果把A和B完全打通搞成同一个模块,违背了高内聚的原则,而目前的A B分开的模块结构,又存在业务逻辑上的这种特殊依赖,产生了让人不太舒服的耦合度
- 场景只是就事论事举个例子,真实的业务场景中肯定不止ABCD这四个模块,B中还会有很多其他的子模块,A中亦然,所以大家没必要纠结我的场景为什么把四个模块要搞出这种奇怪的模块结构,我相信这样的情景在很多业务场景中都存在
h5 video 标签链入七牛线上地址播放前无法显示画面 ?
在项目中动态链入了上传到七牛的线上视频地址。页面中显示了视频,但是没有画面。
点击播放后可以显示出画面。大家知道这种问题怎么处理吗
v8-profiler安装失败
请问有v8-profiler安装成功的么,今天一天装这个模块,没有成功过,windows,Linux都不行
linux
win10
崩溃了~~~
node起的进程怎么才能使用科学上网工具呀?
我用的是lantern,开了全局代理。 把连接放在浏览器可以访问,但是用node进程去访问就不可以,怎么才能让我起的node进程也科学上网呀
[杭州/北京] 阿里云急招前端开发工程师(P6/P7)
职位描述 1、网络监控系统前端开发与维护 2、PC端各产品线易用性改进和技术优化; 3、基于NodeJS的Server端功能设计、开发和实现; 4、研究和探索创新的开发思路和前端技术,结合实际优化工具流程,为生产实践带来帮助; 5、理解产品业务的基础上,提升产品用户体验,技术驱动业务发展;
职位要求 1、精通JavaScript/HTML/CSS; 2、具备丰富的PC端富应用开发经验,并有商业实战案例; 3、对MVC/MVMM有一定的理解,熟练掌握React/Redux或者Vue/Vuex,有中大型单页应用开发经验; 4、熟悉HTTP协议,有高并发项目经验; 5、熟悉Web应用的性能优化,监控,分析方法; 6、有基于Node的Sever端研发经验,或至少熟悉一门后端语言(如:Java/Python/C++); 7、对技术有持续的热情,学习能力出众,逻辑性强,个性乐观开朗,善于合作; 加分项: 1、善于分析理解业务需求 2、有产品思维,敢于提出不同想法与意见 3、node企业级应用开发经验 4、追求代码质量 5、关注前端前沿技术研究
简历请发送到这个邮箱:hongfeng.ly#alibaba-inc.com标题请注明:简历-${姓名}, 谢谢!
Rust-weekly-2019-05-09
>欢迎参与Rust中文:Rust-weekly 参与入口,本文同步于Rust-weekly-2019-05-09
新闻
- Actix系列在最新的Web框架性能排行榜实现所有选项屠榜
- The RustBridge Roadmap for 2019
- This week in Amethyst 16
- A final proposal for await syntax
- This Week in Rust 285
文章
- 理解 Rust 中的 Closure
- 试试看 - 搭建自己的 Rust Cargo Crate 反向代理源
- RUST语言在Windows上的编译安装(GCC ABI)
- Windows Linux子系统使用rustup重新安装Rust
- Rust parallelism for non-C/C++ developers
- Extending Python with Rust
- Rust: How to build a Docker image with private Cargo dependencies
- Explained: Futures in Rust for Web Development
- 用Rust写脚本语言
- 从零开始写 OS
- Kubernetes operators in rust
- Using Rust for Gamedev
- 6 useful Rust macros that you might not have seen before
- World’s First Private Cargo Registry w/ Cloudsmith + Rust
- 如何理解 rust 中的 Sync、Send?
- [译] Rust如何解决依赖地狱
- Compile-time coprocessor codegen, with Rust macros
- Rust Patterns: Enums Instead Of Booleans
- How to build sitemap for images with Rust
- Cross-platform Rust
- Writing your first WebAssembly Project
- How to use datas to build sitemap with Rust Diesel
- 2D Graphics on Modern GPU
- Hawk-Rust Series: Kafka with Rust
- HAWK-Rust Series: Automate Infrastructure using Terraform
- Hawk: Image Recognition Application using Rust and AWS Services
- WebAssembly, Rust, and Edge Computing
- Another Way of Creating struct Instances in Rust
- I underestimated the dangers of Rust FFI
Crates
- vtext - NLP in Rust with Python bindings
- microamp - A (micro) framework for building bare-metal AMP (Asymmetric Multi-Processing) applications
- Graphene - A backup solution for the distributed enterprise platforms of today.
- shipcat - A standardisation tool and security layer on top of kubernetes to config manage microservices
- quiche - quiche is an implementation of the QUIC transport protocol and HTTP/3 as specified by the IETF
- trybuild - Test harness for ui tests of compiler diagnostics
- tobj - Tiny OBJ Loader in Rust
- finshir - A coroutines-driven Low & Slow traffic sender, written in Rust
Rust相关
- 【编程】Rust 教程 | 中文字幕 - 系列视频
- Rust and Tell April 2019: Lin Clark - WASI
- rusty-typescript - A TypeScript compiler written in Rust.
- Stefan Schindler: Parallel Programming with Thread pools and iterators
Rust中文
ISSUES
- 上周发布了10个问题。其中10个问题已经结束,0个问题仍然存在。
PULL-REQUESTS
- 上周,创建,更新或合并了9个拉取请求。
COMMITS
- rustlang-cn -上周有48次提交。
- weekly - 上周有30次提交。
CONTRIBUTORS
这就是上周Rust中文的Github情况,请Watch和Star在Rust中文的Github仓库!以接收下周的每周更新。
One More Thing(有趣)
- GNU Guix 1.0.0 released
- flow9: a cross-platform modern UI for Web, iOS, Android, Windows, Mac, Linux android ios linux mac web windows
- llvm-mca - LLVM Machine Code Analyzer
- A Reading List for Computer Scientists
- Algebraic Data Types in four languages
- Microsoft launches React Native(C++)for Windows
- Announcing WSL 2
- Remote Development with VS Code
- The 5.1 kernel has been released
- 微软宣布 .NET 5 计划,支持跨平台、移动开发
- Google Keynote (Google I/O’19)
- Google I/O 2019 full Livestream
- Microsoft Build 2019 - LIVE Stream - Day 1 (May 6)
- Microsoft Build 2019 // Vision Keynote + Imagine Cup World Championship
- WebAssembly. Neither Web Nor Assembly, All Revolutionary