利用异步事件解决同一事件多次调用的问题
最近在阅读朴大的《深入浅出Node.js》这本书籍,朴大写了一段伪代码,介绍如遇到并发量特别大的同一条SQL语句查询可以用如下方式实现:
var events = require("events");
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";
});
}
};
这段代码利用事件队列的once方法,当有一次新的查询请求过来时先将查询成功的回调函数压入selected事件的事件堆中,然后判断状态,如果事件的状态是没有开始的状态,则调用查询的异步方法,在回调函数中再触发selected事件。 我利用这段代码写了一段类似可执行的程序:
var EventEmitter = require('events').EventEmitter;
var proxy = new EventEmitter();
proxy.setMaxListeners(0);
var status = "ready";
var doSomething = function (callback) {
proxy.once("selected", callback);
console.log("add a listener!");
if (status === "ready") {
status = "pending";
setTimeout(function () {
proxy.emit("selected");
status = "ready";
console.log("resolved");
}, 1000);
};
};
for (var i = 0; i < 20; i++) {
setTimeout(function (i) {
return (function (i) {
doSomething(function () {
console.log(i)
});
})(i)
}, 100 * i, i);
};
首先,我用setTimeout(func, 1000)
注册一个1s后发生的事件来模拟查询SQL这类异步事件,同时,利用循环,每隔100ms注册一个doSomething的事件,事件的回调函数就是将注册事件的序号打印出来,由于是异步回调,我们得利用闭包来将i封装。
这段代码运行的结果将是类似如下:
希望能帮助大家理解!第一次写Blog,可能语句不太通顺,请见谅!