前言
从 js 中的事件模型,到 Yii2 中的是事件,再到 nginx 事件机制。我愈发想要搞清楚事件究竟是怎么会事了,现在我们仅从概念上去深入理解事件。
js 中的事件
两个小 demo
HTML 有能力使 HTML 事件触发浏览器中的动作(action),比如当用户点击某个按钮时候,就会触发 按钮点击 事件,js 监听到这个事件之后就可以做出相应的动作了。
<input type="button" onclick="fun()">
//通过JS代码指定属性值:
var btn = document.getElementById('.btn');
btn.onclick = fun;
//移除监听函数:
btn.onclick = null;
这是简单的事件例子,这个事件没什么可说的。
稍微复杂一点的如一下:
// 取 btn 对象
var btn = document.getElementById('.btn');
// 事件绑定
btn.addEventListener(‘click’, showMessage, false);
// 事件移除监听
btn.removeEventListener(‘click’, showMessage, false);
在该事件模型中有三个过程:1. 事件捕获;2. 事件处理;3. 事件冒泡
在这个两个案例中,事件是与浏览器或文档交互的瞬间,如点击按钮,填写表格等,它是 js 与 HTML 之间交互的桥梁。值得注意就是一个事件流的概念。
为什么 js 和 html 之间要引入“事件”这个概念
在 web前端,以及其它 GUI 编程上,操作视图的只能有一个进程,否则如果两个进程同时修改一个对象那不就要打架了。在一个进程的前提下,要想获取用户的操作要么就是一直轮询,要么就是中断。显然轮询不合理啊,那么引入事件,用户做的操作放入消息循环中,js 进程只需要从循环中取消息不断地取执行操作就可以了。
PHP框架Yii2 中的事件
在服务端开发逻辑中,使用事件,可以在特定的时点,触发执行预先设定的一段代码,事件既是代码解耦的一种方式,也是设计业务流程的一种模式。现代软件中,事件无处不在,比如,你发了个微博,触发了一个事件,导致关注你的人,看到了你新发出来的内容。
其实 Yii2 中的事件就是一个观察者模式,比如说在登陆之后需要做一些列操作,记录日志,通知粉丝该用户已登陆,更新购物车等。那么就可以给日志,更新购物车等绑定登陆成功事件,在登陆成功之后触发登陆成功事件即可。
class UserController extends Controller {
// 定义事件名字
const EVENT_USER_LOGIN = 'user_login';
public function __construct(){
// 绑定事件
$this->on(self::EVENT_USER_LOGIN,['app\models\OLog','add']);
$this->on(self::EVENT_USER_LOGIN,['app\models\Admin','sendMail']);
$this->on(self::EVENT_USER_LOGIN,['app\models\User','updateCart']);
}
public function actionIndex(){
// 这里有一些代码.....
Yii::$app->user->login($user);
$this->trigger(self::EVENT_USER_LOGIN);
}
}
不用事件行不行,可以。只不过代码更不容易维护而已,结构会越来越臃肿。
Node.js 的异步事件
Node.js 这门神奇的语言有出场了,基本的事件和上述一致,但 Node.js 是异步的啊,所以就有了异步事件。
const fs = require('fs');
const EventEmitter = require('events');
class WithTime extends EventEmitter {
execute(asyncFunc, ...args) {
this.emit('begin');
console.time('execute');
asyncFunc(...args, (err, data) => {
if (err) {
return this.emit('error', err);
}
this.emit('data', data);
console.timeEnd('execute');
this.emit('end');
});
}
}
const withTime = new WithTime();
withTime.on('begin', () => console.log('About to execute'));
withTime.on('end', () => console.log('Done with execute'));
withTime.execute(fs.readFile, __filename);
疑惑
其实只是对事件有了一个简单的了解,后续继续深入探索吧。
--EOF--
网友评论