使用JavaScript发布订阅设计模式实现Ajax请求节流
1. 说明一下主要逻辑
当我们发送多个请求时使用的时同一个接口,并且这个接口支持多个参数获取多个条数据,而我们不想要每次请求一条数据就发送一条请求
而是在指定的时间段类发送一次请求,得到一些数据,然后把这些数据 返回到对应的发起请求的地方
2. 使用场景
比如像QQ聊天会有一个联系人列表,这个列表每个联系人会有一个头像,我们可以通过一个接口获取指定的用户的头像图片链接,也可以一次性获取多个头像链接,只需要有多个用户ID即可
但是一般都是会在联系人列表渲染时,每渲染一个联系人列表发送一次请求,这样就会发送多次请求,造成不必要的浪费,我们选择获取联系人列表之后只发送一次请求就行
3. 实现一个简单的发布订阅者模式
let event = { events:[], /** * 添加订阅 * @param {[String]} event [description] * @param {Function} fn [description] * @return {[undefined]} [description] */ on(event, fn){ if(!event || !fn) return; let hasEvent = this.hasEvent(event); if(hasEvent){ hasEvent.handler.push(fn); } else { this.events.push({ type: event, handler: [ fn ] }); } }, /** * 发布订阅 * @param {[String]} event [description] * @param {...[any]} arg [description] * @return {[undefined]} [description] */ emit(event, ...arg){ let hasEvent = this.hasEvent(event); if(hasEvent){ hasEvent.handler.forEach(fn => fn(...arg)); } else { console.log('该事件还没有订阅'); } }, /** * 判断该事件是否已经注册 * @param {[String]} event [description] * @return {Boolean} [description] */ hasEvent(event){ return this.events.find(ele=>ele.type === event); }, /** * 移除订阅事件 * @param {[type]} event [description] * @param {Function} fn [description] * @return {[type]} [description] */ removeEvent(event, fn){ if(event && fn){ let eve = this.hasEvent(event); if(eve){ eve.handler.splice(eve.handler.indexOf(fn), 1); } } if(event && !fn){ for(let i = 0; i< this.events.length; i++){ if(this.events[i].type === event){ this.events.splice(i, 1); break; } } } } }
3. 书写Ajax请求函数
function ajax(url, data){ clearTimeout(ajax.timer); if(!ajax.dataArr){ ajax.dataArr = []; } ajax.dataArr.push(data); ajax.timer = setTimeout(()=>{ // 限制在300毫秒内的请求会只请求一次 fetch(url, { method: 'POST', body: JSON.stringify(ajax.dataArr) }).then(res=>res.json()).then(res=>{ event.emit('send', res); }) }, 300); return new Promise((resolve, reject)=>{ event.on('send', (res) => { resolve(res.filter(item=>item.id == data.id)[0]); }); }) }
4. 准备一个模拟json数据的 data.json 文件
[{ "id": 1, "content": "文本内容11111" },{ "id": 2, "content": "文本内容22222" },{ "id": 3, "content": "文本内容33333" },{ "id": 4, "content": "文本内容44444" },{ "id": 5, "content": "文本内容55555" },{ "id": 6, "content": "文本内容66666" },{ "id": 7, "content": "文本内容77777" },{ "id": 8, "content": "文本内容88888" }]
5.发送Ajax请求
for(let i = 1; i<=8; i++){ ajax('./data.json', {id: i}).then(res=>{ console.log(res); }) }
6. 返回的数据