假设有这样的函数
<body>
<button id="x">点击</button>
<script>
const button = document.getElementById('x')
const fn = () => console.log('hi')
</script>
</body>
如何在不点击 button 的情况下触发 fn 函数(用 js 触发函数
只需要在 script 加上这些代码
const button = document.getElementById('x')
const fn = () => console.log('hi') //声明事件处理函数
button.addEventListener('click', fn) //监听 click 事件
//button.removeEventListener('click', fn) //取消监听
setTimeout(() => {
//派发 触发 发射 click 事件
button.dispatchEvent(new Event('click'))
}, 5000);
如何添加上事件名
class EventEmitter {
constructor() {
this.queue = { } //构造一个数组 queue
}
addEventListener(name, fn) {
this.queue[name] = this.queue[name] || [] //如果有this.queue[name]则赋值,如果没有则等于空
this.queue[name].push(fn) //往数组里面添加函数
}
removeEventListener(name, fn) {
if(this.queue[name] === undefined) { return } //防御性
const index = this.queue[name].indexOf(fn)
if(index < 0) return
this.queue[name].splice(index, 1) //删掉数组里的函数
}
dispatchEvent(name, data) {
this.queue[name]?.forEach(fn => fn(data)) //判断this.queue[name]是否存在,如果是则遍历数组,把数组里的函数全部执行一遍,不是则什么都不做
}
}
const obj = new EventEmitter()
const fn = (data) => console.log(data) //声明函数,
obj.addEventListener('kenny', fn) //添加函数
setTimeout(() => {
obj.dispatchEvent('kenny', '你好') //四秒之后触发函数
}, 4000);
如何添加参数?
dispatchEvent(name, ...args) {
this.queue[name]?.forEach(fn => fn.call(undefined, ...args)) //判断this.queue[name]是否存在,如果是则遍历数组,把数组里的函数全部执行一遍,不是则什么都不做
}
发布订阅总结
发布订阅的特点?
- api 提供了 addEventListener / on / subscribe
- api 提供了 dispatchEvent / emit / trigger
- api 提供了 removeEventListener / off / unsubscribe
- 满足上述条件的对象被称为 EventEmitter,实现了发布订阅模式
- 把回调(函数)放在队列(数组)里,等待被逐个调用
发布订阅解决了什么问题?
- 所有异步任务都可以用发布订阅来管理
- 先订阅成功事件和失败事件
-
- xhr.on('load'); xhr.on('error')
- 再在任务完成时触发成功或失败事件
-
- xhr.emit('load'); xhr.emit('error')
- 这就是一个通用的异步任务管理方案
缺点是什么?
- 事件少时还行;但当事件过多时,很难管理
this.queue[name]?.forEach(fn => fn(data)) //核心代码
promise
promise 对象用于表示一个异步操作的最终完成(或失败)及其结果值,代码示例如下
function ysz() {
return new Promise((resolve, reject) => { //返回一个 promise,
setTimeout(() => {
const n = Math.floor(Math.random() * 6) + 1
resolve(n) //成功时调用resolve(data),失败时调用reject(reason)
}, 3000);
})
}
/* resolve 会去调用 success,reject 会去调用 fail
ysz().then(success, fail) //用then方法返回一个 promise,传入 promise 的成功和失败情况的回调函数作为参数
function success(data){ //声明成功函数,传入 data
console.log('成功, 点数为' + data)
}
function fail(reason){ //声明失败函数,传入 reason 作为失败原因
console.log('失败了,原因是' + reason);
Promise 的三种状态
- pending 待定,即初始状态,既没有被兑现,也没有被拒绝
- fulfilled 解决,操作成功完成
- rejected 拒绝,操作失败
状态变化只有三种情况:待定 => 解决、待定 => 拒绝、待定 => 待定,没有其它
Promise 的链式掉用
即一个 promise 之后又是一个 promise,因为then() 方法返回一个 promise,因此可以将进一步的操作与一个变为已敲定状态的 promise 关联起来
.then(success, fail).then(success2, fail2)
ysz().then((n) => {console.log(n>3?'大':'小'); return n}, //如果成功,则
(reason) => {console.log('失败了,因为' + reason);throw reason}
).then((data) => {console.log(data)},
(reason) => {console.log('失败了,原因是' + reason);})