前端:如何处理AJAX请求的重复使用

 在开发前端时,前端X请求我们经常使用AJAX来初始化数据并动态渲染在页面上,何处但是重复在遇到一连串的相同数据都要进行请求时,就有可能对同一个API 发出并发请求,使用然而,前端X请求因为这些请求是何处同时发出,因此响应也非常可能是重复相同的,这样讲可能不够清楚,使用直接写一个简易的前端X请求范例来解释这个情况。

实际范例

首先我们先撰写一个API:

https://localhost:3000/api/v1/users/:uuid 

这个API的何处回传值如下:

{      "name":"Username{ uuid}",     "uuid":"{ uuid}" } 

随后开一个Vue的demo,并且先通过Axios写一个请求的重复函数:

// fetch-user.js const axios = require(axios); module.exports = (uuid) => {      let uri = `http://localhost:3000/users/${ uuid}`;     return new Promise(resolve => {          axios.get(uri).then(resolve);     }) }; 

然后我们在Vue例子中新增一个User Component(User.vue)来负责渲染并请求接口:

<template>     <div v-if="init">         <ul>             <li>{ { user.name}}</li>             <li>{ { user.uuid}}</li>         </ul>     </div> </template> <script>     const fetchUser = require(../lib/fetch-user);     export default {          name: User,         data: function() {              return {                  init: false,                 user: null             }         },         props: {              uuid: String         },         async mounted() {              const response = await fetchUser(this.uuid);             this.init = true;             this.user = response.data;         }     } </script> 

最后将用户组件放入App.vue中:

<template>     <div id="app">         <user uuid="user-uuid"></user>         <user uuid="user-uuid"></user>         <user uuid="user-uuid"></user>         <user uuid="user-uuid"></user>         <user uuid="user-uuid"></user>         <user uuid="user-uuid"></user>         <user uuid="user-uuid"></user>         <user uuid="user-uuid"></user>         <user uuid="user-uuid"></user>         <user uuid="user-uuid"></user>         <user uuid="user-uuid"></user>         <user uuid="user-uuid"></user>         <user uuid="user-uuid"></user>         <user uuid="user-uuid"></user>         <user uuid="user-uuid"></user>     </div> </template> <script> import User from ./components/User; export default {      name: App,     components: {          User     } } </script> 

接着我们看一下显示结果:

这样就正确显示了,然而这里有一个问题非常值得注意:

我们打开开发者模式就会发现,使用每个组件向该API发出了请求,前端X请求因此就产生了10次的何处并发请求,但是服务器托管重复在这种情况下,实际上我们仅需要让一个请求出去,另外9个元件等待这个请求的响应然后重新使用即可。

改进的方法

接下来将讲解要如何实现关于在同一个组件之间唯一指定API请求一次并分配请求,我们会用到这个元件EventTarget,这个元件有点类似Node.js中的EventEmitter,主要就是用于接收事件。

随后我们改写fetchUser()函数:

const axios = require(axios); /**  * 这个 class 是用于存储 Response Data 的 Event 衍生类  */ class FetchCompleteEvent extends Event {      constructor(type, data) {          super(type);         this.data = data;     } } // 用于请求成功时使用的事件监听器 const eventEmitter = new EventTarget(); // 用于请求失敗时使用的事件监听器 const errorEmitter = new EventTarget(); /**  * 用于存储 URI 以及是否当前正在请求的状态,如:  * http://localhost:8000/users/foo => true 代表已经发出请求,正在等待 Response  * http://localhost:8000/users/bar => false 代表当前没有请求在路上  */ const requestingList = new Map(); module.exports = (uuid) => {      let uri = `http://localhost:3000/users/${ uuid}`;     return new Promise((resolve, reject) => {          // 如果没有记录,或者尚未处于请求状态         if (!requestingList.has(uri) || !requestingList.get(uri)) {              // 进入之后立即将请求状态设为 true             requestingList.set(uri, true);             // 请求 URI             axios.get(uri).then(response => {                  // 完成请求之后将请求状态设为 false                 requestingList.set(uri, false);                 // 发出一个事件通知來告诉 callback 请求完成了                 eventEmitter.dispatchEvent(new FetchCompleteEvent(uri, response));                 resolve(response);             }).catch((e) => {                  // 请求失败也算是请求完成,将请求状态设为 false                 requestingList.set(uri, false);                 // 发出一个事件通知來告诉 callback 请求失败了                 errorEmitter.dispatchEvent(new FetchCompleteEvent(uri, e));                 reject(e);             })         }          // 当目前指定的 URL 处于请求状态,源码库则不做任何事情         else {              // 向成功的事件监听器注册,当完成之后 resolve()             eventEmitter.addEventListener(uri, (event) => {                  resolve(event.data);             });             // 失败之后 reject()             errorEmitter.addEventListener(uri, (event) => {                  reject(event.data);             })         }     }); }; 

接着我们重新运行前端应用程序并查看结果:

结果与一开始一模一样,而是当时我们打开开发者模式就会发现:

请求已经被减少到剩下一个了,这是因为所有的元件都重复使用了一个同一个响应。通过这种方法将可以大大减少服务器的负载以及前端的运行时间。

总结

并非每一种情况下都可以使用这种方式来请求资源,如:每次请求资源都一定会发送不一样的API就不能使用这种方式进行API调用,但是像是上述范例中的用户资料,电商网站中的商品资料或文章等,类似能够确保在极短时间之内资源都是相同的API就可以使用这种方式来进行操作。

扩展阅读

https://dev.to/floatflower/ajax-414j

参考资料

1.https://developer.mozilla.org/zh-TW/docs/Web/API/EventTarget

亿华云计算
应用开发
上一篇:MWC 2023 |汇聚产业力量,共创“新一代智能运维”
下一篇:什么是PDU?如何为数据中心选择合适的PDU