WdBly Blog

懂事、有趣、保持理智

周维的个人Blog

懂事、有趣、保持理智

站点概览

周维 | Jim

603927378@qq.com

推荐阅读

Node中的异步编程

有异步I/O,必有异步编程,今天聊一聊异步编程,Node异步的高性能为它带来了高度的赞誉,而异步编程也为其带来部分的诋毁。

Node带来的最大特性莫过于基于事件驱动的非阻塞I/O模型,这是它的灵魂所在。非阻塞I/O,可以使CPU与I/O并不相互依赖等待,让资源得到更好的利用。

异步编程带来的问题

  • 错误捕获问题

  • 回调地狱问题: Node相对于浏览器,存在着异步多级依赖问题,对于Node而言,事务中存在多个异步调用的场景比比皆是,比如遍历一个文件目录。

多层回调虽然可以达到目的,但并没有利用好异步I/O带来的并行优势。

  • 阻塞代码:如sleep函数。

  • Node中存在的多线程编程

  • 同步式编程支持

与问题相比,解决问题的方案总是更多,接下来我们一一解决。

事件监听器(发布订阅模式)

Node自身提供的events模块是发布/订阅模式的一个简单实现, 如下:

const EventEmitter = require('events'); class MyEmitter extends EventEmitter {} const myEmitter = new MyEmitter(); myEmitter.on('event', () => { console.log('触发事件'); }); myEmitter.emit('event');

事件监听器模式是一种广泛用于异步编程的模式,是回调函数的事件化,是事件驱动的一种实现,通过事件绑定,和回调函数的方式运行程序。 区别于事件循环中的异步事件回调, 事件监听器的触发是由开发者自由控制的。

事件监听器协调于多个异步场景

在Node事件监听器中一般是一个触发器对应多个侦听器(一次emit会触发多个on侦听器), 但是也会存在着多次emit对应一次on的情况,如:当文件1和文件2都读取完毕后再执行处理事件:传统写法如下:

// 用偏函数原理(利用了闭包)协调多个异步结果 var after = function (times, callback) { var count = 0, results = {}; return function (key, value) { results[key] = value; count++; // 当done执行两次时触发callback; if (count === times) { callback(results); } }; }; var handleEvent(res) { console.log(res); } var done = after(2, render); fs.opne("file1", res => { done("file1", res); }) fs.opne("file1", res => { done("file2", res); })

用事件监听器方式则是将done方法放入事件绑定的回调中即可。

利用Promise协调于多个异步场景

利用use、next和async解决中间件执行

缓存失效造成雪崩问题

在高并发,大量数据访问到程序时,若是缓存失效,则大量请求同时涌入数据库,导致数据库长时排队,造成的雪崩问题。比如应用刚刚启动时或者缓存过期的差时。

利用事件队列和once方法解决此问题:

var proxy = new events.EventEmitter(); var status = "ready"; var select = function (callback) { proxy.once("selected", callback); if (status === "ready") { status = "pending"; db.select("SQL", function (results) { proxy.emit("selected", results); status = "ready"; }); } };

参考资源:
《深入浅出Node.js》

提交

全部评论0

暂时没有评论...