<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Scott Hu</title>
    <description>The latest articles on DEV Community by Scott Hu (@coderhu).</description>
    <link>https://dev.to/coderhu</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F921028%2Fdf0397f5-e26a-4f95-bae1-0094d0595cbe.jpg</url>
      <title>DEV Community: Scott Hu</title>
      <link>https://dev.to/coderhu</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/coderhu"/>
    <language>en</language>
    <item>
      <title>30 months of open source: How I maintain the Next-Gen request tool</title>
      <dc:creator>Scott Hu</dc:creator>
      <pubDate>Tue, 03 Sep 2024 09:13:46 +0000</pubDate>
      <link>https://dev.to/coderhu/30-months-of-open-source-how-i-maintain-the-next-gen-request-tool-4l5b</link>
      <guid>https://dev.to/coderhu/30-months-of-open-source-how-i-maintain-the-next-gen-request-tool-4l5b</guid>
      <description>&lt;p&gt;Two years ago, I designed and developed a JavaScript request strategy library called alovajs. Since its promotion in April 2023, it has received acclaim from developers around the world and has garnered over 2700+ stars, including recognition from experts at major companies.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fa3uky9janxfg1yp9176b.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fa3uky9janxfg1yp9176b.jpg" alt="received acclaim" width="800" height="235"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Currently, &lt;a href="mailto:alova@3.x"&gt;alova@3.x&lt;/a&gt; has been released, positioned as "the next-generation request tool for streamlined workflows."&lt;/p&gt;

&lt;p&gt;I have been maintaining it without compensation for 30 months, and the version has reached 3.x. During this period, through continuous reflection, rejection, and rethinking, I aimed to achieve something that other request tools have not done, to become a tool that can truly help front-end development. I believe I have found a reliable direction.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;That is, to create a "next-generation request tool for streamlined workflows", maximizing the assistance to front-end development in streamlining the API integration process.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Below is the exploration story of alovajs, which is also the story of an open-source project from its inception.&lt;/p&gt;

&lt;p&gt;If you are interested in alovajs, I sincerely invite you to join the community and make progress together.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;a href="https://discord.gg/S47QGJgkVb" rel="noopener noreferrer"&gt;Join the Discord community&lt;/a&gt; &lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  alovajs Originated from a Small Project, but Its Mission is to Sail the Ocean
&lt;/h2&gt;

&lt;p&gt;One day in March 2022, due to certain circumstances, I conceived the idea of developing an App called "Con of goal." Inspired by some apps, I hoped that "Con of goal" could achieve delay-free data requests and submissions, that is, an immediate response mode, even under weak or no network conditions. However, after searching online and not finding a suitable solution, and similar optimistic update solutions not meeting the needs, my damn desire to share led me to decide to implement it in the form of a request library, which was the starting point of alovajs, but it didn't have a name at that time.&lt;/p&gt;

&lt;h3&gt;
  
  
  Designing alovajs
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;The beginning of a library is not design, not development, but clarifying the needs&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;pro Tips: It is strongly recommended that you first briefly understand the &lt;a href="https://alova.js.org/tutorial/getting-started/introduce" rel="noopener noreferrer"&gt;overview section&lt;/a&gt; of alovajs to better understand the following content.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;At that time, there was no product positioning, just creating a JavaScript library to meet my own needs. I studied existing request libraries and listed the following needs:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Support for seamless data interaction mode, that is, under network disconnection, it can still be submitted without delay, without the user's perception&lt;/li&gt;
&lt;li&gt;Designed according to the popular useHook of the time, making the interface more user-friendly&lt;/li&gt;
&lt;li&gt;A set of code supports multiple frameworks such as Vue, React, etc., and JavaScript operating environments such as browsers, React Native, UniApp, and Taro, etc.&lt;/li&gt;
&lt;li&gt;Consistent usage in multiple JavaScript environments&lt;/li&gt;
&lt;li&gt;Considering the caching function of react-query is very good, this should also be added&lt;/li&gt;
&lt;li&gt;Due to the influence and simplicity of axios, make alovajs easy to get started with, and the design should be similar to axios&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Then, based on the needs, the library's API was designed.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  For needs 1, it was the starting point for me to do alovajs, but it was not simple. The design at the time was to add a &lt;code&gt;silent&lt;/code&gt; parameter in the useHook configuration, which could immediately respond to the success callback, but it was later proven to be problematic and redesigned, which is now the &lt;a href="https://alova.js.org/tutorial/strategy/sensorless-data-interaction/" rel="noopener noreferrer"&gt;seamless data interaction strategy&lt;/a&gt; &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fw0h4ycf5wazavsj3r0ql.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fw0h4ycf5wazavsj3r0ql.jpg" alt="Image description" width="491" height="235"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;For needs 2, three core useHooks were designed: useRequest, useWatcher, and useFetcher. This is very familiar to everyone, such as ahooks' useRequest, vueuse's useAsyncState, react-query, and swr, needless to say, it is indeed very convenient.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Since the useHook design is used, different frameworks will have different state management, but I don't want to create a JavaScript library for each framework like react-query. Therefore, for needs 3, the specifications for stateHook adapters, request adapters, and storage adapters were designed, and different adapters can be written according to the specifications, separating the framework environment and runtime environment-related logic into separate modules.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;For needs 4, the method instance proxy pattern was designed, and the method instance proxy calls the hook functions of different adapters, so that even if you develop any application, you can get started with alovajs without any unfamiliarity, and it can also be seamlessly transplanted.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;For needs 5, similar JavaScript libraries implement caching in the form of custom keys, but my idea is to focus on request information. The common scenario is that when requesting the same interface with the same request method and parameters, it is necessary to hit the response data of the last time. Why don't we use these request information as caching keys? Therefore, alovajs has designed an automatic caching mechanism, which is enabled by default on GET requests.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;For needs 6, refer to and learn from axios.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These designs have indeed been proven over time. alovajs has perfectly compatible with Vue, React, Svelte frameworks through the adapter method, and can also run in various JavaScript environments such as browsers, React Native, UniApp, and Taro, while maintaining a consistent usage method, which has given me a glimmer of hope.&lt;/p&gt;

&lt;p&gt;In the following months, although alovajs was released, it has not been promoted. On the one hand, it is because I used it in the "Con of goal" project. Although it has been tempered and improved in this project, it is still very incomplete, and the positioning is not clear. The initial version introduction is like this.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxq6a11ueekhktr7kcgzw.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxq6a11ueekhktr7kcgzw.jpg" alt="initial version of alovajs" width="718" height="680"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Later, the "Con of goal" project was aborted, but alovajs is still persisting.&lt;/p&gt;

&lt;h3&gt;
  
  
  alovajs' Direction Exploration
&lt;/h3&gt;

&lt;p&gt;With the obsession of once being an Internet product manager, I still hope to make alovajs a differentiated product. I often ask myself, what is the difference between alovajs and other request libraries? Why should users use alovajs? It is indeed different from other libraries in design, which is not a question that can be answered immediately. Later, I tried to position the direction of the request library as a "lightweight request library" and a "multi-end unified request library", but they were all denied by myself, because these cannot bring substantial help to developers, and they cannot be called advantages.&lt;/p&gt;

&lt;p&gt;In September 2022, an opportunity made me discover the excellent request library based on Vue, vue-request. Its &lt;code&gt;usePagination&lt;/code&gt; and &lt;code&gt;useLoadMore&lt;/code&gt; immediately inspired me. This form of pagination implementation made me realize that this is also what I want. At the same time, it made me realize the power of useHook. I can divide the module according to the request scenario, use different useHooks for different scenarios, and the previously implemented seamless data interaction is actually one of the scenarios. If this is the direction, developers can choose different useHooks according to different request scenarios, which not only improves development efficiency and reduces coding complexity, but also prevents junior front-end from writing inefficient code, and can make better use of the core features of alovajs to achieve better performance and less server pressure. request features, so far, the "lightweight request strategy library" was chosen by me.&lt;/p&gt;

&lt;p&gt;Then, in order to guide the future design direction of alovajs, I also refined and abstracted the request scenario model (RSM) of alovajs, mainly divided into the following four processes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Request timing -&amp;gt; Request behavior -&amp;gt; Request event -&amp;gt; Response processing
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Let's do it&lt;/strong&gt;, I started to reconstruct alovajs 2.0 according to this positioning, separated the seamless data interaction function from 1.0, and designed a middleware mechanism to adapt to the development of more request scenario strategy useHooks, studied and developed the pagination strategy and seamless data interaction strategy.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;The pagination strategy of alovajs is what I think is the most useful &lt;code&gt;usePagination&lt;/code&gt;. It uses the caching function of alovajs to achieve pre-loading of front and back page data, pagination data search, request-level debouncing, and provides automated management of new editing and deletion functions, as well as refreshing the data of a specified page code without resetting.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The seamless data interaction strategy took me 4 months, constantly encountering dead ends, and constantly redesigning the result. It has achieved a strategy that allows users to interact with data without delay even in weak or disconnected network environments, and it can also more stably ensure the success of the request. I designed a virtual data thing, which can be used as a placeholder for response data before the response, making users feel that it is an immediate response, and then replace the virtual data with real data after the response is successful. According to the current exploration results, its usage scenarios can be editor-like applications, system setting modules, and some simpler lists.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Later, request strategy modules such as &lt;code&gt;useForm&lt;/code&gt;, &lt;code&gt;useAutoRequest&lt;/code&gt;, and &lt;code&gt;useSSE&lt;/code&gt; were also added, but this is far from enough.&lt;/p&gt;

&lt;h3&gt;
  
  
  The idea of the Next-Generation Request Tool
&lt;/h3&gt;

&lt;p&gt;On May 13, 2023, I received such an issue on github&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkeuj13zuwfu1jpqbtixm.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkeuj13zuwfu1jpqbtixm.jpg" alt="Support for openAPI" width="800" height="345"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;At first, I didn't pay much attention to this issue, just simply understood the function of automatically generating request code for openAPI, and thought it was very good, but due to limited energy, I didn't think deeply about it, and I hadn't been thinking about the direction of alovajs at that time. But recently, I would occasionally think about the direction of alovajs, and this issue that is still open has always come to my mind, and then quietly changed the label of this issue from "feature-request" to "feature-request:confirmed".&lt;/p&gt;

&lt;p&gt;At the same time, this issue made me realize that alovajs can also narrow the collaboration distance between front-end and back-end, and further simplify the front-end development workflow. This is the development direction I set for alovajs 3.0:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;alovajs will help developers simplify the API integration workflow to the greatest extent, you only need to specify which API to use (this is also the result of thinking for 3 months)&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyfylpucrrvuyf9zaj2dw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyfylpucrrvuyf9zaj2dw.png" alt="streamline flows" width="800" height="244"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;My specific plan is as follows:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;The steps 1, 2, 3, 4, 6 in the above figure are solved by automatically generating API code, but our generation plan will go further compared to tools like &lt;code&gt;openapi-generator&lt;/code&gt;. It will automatically generate complete ts type, complete description request functions, whether it is a js project or a ts project, there is no need to introduce, let developers call as convenient as directly calling &lt;code&gt;location.reload&lt;/code&gt;, and the request function can directly see the complete description and request parameter type prompts.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Since the automatically generated request functions have complete descriptions and type prompts, the vscode plugin completes the interactive way to quickly retrieve the required APIs, and you no longer need to refer to the API documentation.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Solve the problem of the front-end and back-end collaboration gap, and any changes in the interface can be automatically notified to the front-end. If there are changes found during the project construction, an error will be thrown to stop the construction. If it is a ts project, an error will also be thrown during compilation, and the change records can also be viewed through the vscode plugin.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Here is &lt;a href="https://youtu.be/bAzPUYYSKT4" rel="noopener noreferrer"&gt;the demo video of vscode extension&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;How to solve step 6 "write complex request logic"? Of course, it is to use the request strategy module, which has the characteristics of high performance and scene-based, and users can use a very small amount of code to implement various scene request functions.&lt;/p&gt;

&lt;p&gt;In March 2024, the development plan for &lt;a href="mailto:alova@3.0"&gt;alova@3.0&lt;/a&gt; was formulated, and it took 4 months to restructure almost the entire project with &lt;a href="https://github.com/MeetinaXD" rel="noopener noreferrer"&gt;core member MeetinaXD&lt;/a&gt;, and there are many optimizations:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;The underlying architecture was redesigned, and a set of hooks can be used simultaneously in Vue, React, Svelte, and even in the Vue options style.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The available range has been increased to the server side. You can use alova in server-side frameworks such as express, koa, and nestjs, and new server-side request strategy server hooks have been added.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;10 configurations in &lt;a href="mailto:alova@2.x"&gt;alova@2.x&lt;/a&gt; were deprecated, and 9 designs were optimized.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;In addition, the most important part of 3.0, the vscode plugin, which is in charge of our &lt;a href="https://github.com/czhlin" rel="noopener noreferrer"&gt;core member czlin&lt;/a&gt;, is also available, and it has basically achieved the goals we set at the beginning.&lt;/p&gt;

&lt;p&gt;So far, &lt;a href="mailto:alova@3.0"&gt;alova@3.0&lt;/a&gt; has passed the beta period and can be stably used in the production environment.&lt;/p&gt;

&lt;h2&gt;
  
  
  Only by continuous exploration can we become better
&lt;/h2&gt;

&lt;p&gt;At that time, an article that was criticized, &lt;a href="https://medium.com/p/12c014833b04" rel="noopener noreferrer"&gt;It's time to replace your axios&lt;/a&gt; made it to the hot search.&lt;/p&gt;

&lt;p&gt;It was indeed not that good when it was just launched, but I know that every product is not achieved overnight, and it needs time to precipitate.&lt;/p&gt;

&lt;p&gt;The Apple 1 computer didn't even have a case at the beginning&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsnn91jahllbxauymk6qc.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsnn91jahllbxauymk6qc.jpg" alt="macintosh" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The development journey of Vue is also a process of continuous exploration and progress&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6ovzjtss961nmroc4ynu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6ovzjtss961nmroc4ynu.png" alt="vue development history" width="800" height="754"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I am just moved by such a product journey, and persisting in doing one thing is the easiest way to succeed. Good products need to be tested for several years, let alone alovajs, which has only been around for about 1.5 years, and has only been contacted by some people for 8 months. During this period, it has also been exploring better solutions and moving forward step by step.&lt;/p&gt;

&lt;p&gt;alovajs initially designed useHooks including useRequest, useWatcher, useEffectWatcher, useManual, useController, and then gradually reduced to only three core hooks: useRequest, useWatcher, and useFetcher.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fv9z7j9852iv3tqce5mqb.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fv9z7j9852iv3tqce5mqb.jpg" alt="Image description" width="498" height="566"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;a href="https://github.com/alovajs/alova/commit/a6d2f245eaab09d7395c0c5a3fab4615cea5ac2e" rel="noopener noreferrer"&gt;Commit address&lt;/a&gt; &lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In the design of parallel requests, whether to implement a form similar to Promise.all, or the current form of binding to the onSuccess function, I have been entangled in several versions, changed back and forth, and the following is the design of the abandoned responder of that year.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjpp6ftfcyczdbkfib0wu.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjpp6ftfcyczdbkfib0wu.jpg" alt="The design of the abandoned responder that year" width="800" height="406"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Commit record not found&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In order to be compatible with asynchronous caching schemes such as IndexedDB, I initially tried to design the storage adapter as an asynchronous function, but it would bring a series of problems, and then tried to implement the event mechanism through StorageConnector, which is still not perfect enough, and finally to the current custom localCache asynchronous function mechanism.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6l5ys69uuw0s9ipmwk8z.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6l5ys69uuw0s9ipmwk8z.jpg" alt="A copy of the new project" width="800" height="810"&gt;&lt;/a&gt; &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;a href="https://github.com/alovajs/alova/commit/86a4e47ce5c02884e91ca69778672234a7ec389a" rel="noopener noreferrer"&gt;Commit address&lt;/a&gt; &lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I also thank friends who have supported and contributed to alovajs. The following are a few screenshots, and there are many contributions that are not included.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5dpmdjy7odv2t2lwjdtc.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5dpmdjy7odv2t2lwjdtc.jpg" alt="variant of issues" width="800" height="512"&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ff3x9q606too8zds9g3jk.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ff3x9q606too8zds9g3jk.jpg" alt="image.png" width="800" height="321"&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmo72akmzn6ipzc2hxld1.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmo72akmzn6ipzc2hxld1.jpg" alt="image.png" width="800" height="314"&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;And continuously supplement the details of the document and improve the best practices, boldly try the cache version plan for the cache recovery mode, and in order to provide complete ts type prompts for alovajs, try to use automatic type inference to reduce the trouble of developers defining types, and indeed spend a lot of effort to optimize and compatible with different UI frameworks, etc.&lt;/p&gt;

&lt;p&gt;Among them, the document has been greatly changed two to three times. I am grateful to &lt;code&gt;@Orange Peel&lt;/code&gt; for providing the first document modification opinion, and &lt;code&gt;@Well&lt;/code&gt; for providing the second document modification opinion, and then our document has such a reputation.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;@green tree&lt;/code&gt; helped me open up new ideas for alova.&lt;/p&gt;

&lt;p&gt;Many things are no longer clear, and the records on npmjs tell me that 146 versions have been released.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkrngec5dj9n6590ornox.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkrngec5dj9n6590ornox.png" alt="191 publish versions" width="440" height="359"&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;There are also many people on github who have raised bugs, and I have also responded and fixed them in the first time. I am really very grateful. If I can't judge the problem immediately, I will also reproduce it on codesandbox, and use this demo as a bridge for communication with users.&lt;/p&gt;

&lt;h2&gt;
  
  
  The END
&lt;/h2&gt;

&lt;p&gt;Thank you very much for your reading🤗, no matter how difficult it is, the road still needs to continue.&lt;/p&gt;

&lt;p&gt;If you recognize alovajs, please go to &lt;a href="https://github.com/alovajs/alova" rel="noopener noreferrer"&gt;Github&lt;/a&gt; to give it a star.&lt;/p&gt;

&lt;p&gt;If you want to understand alova, you can &lt;a href="https://alova.js.org" rel="noopener noreferrer"&gt;visit the official website&lt;/a&gt;, where you can find more detailed documentation and example code to help you better understand and use this tool.&lt;/p&gt;

&lt;p&gt;If you have any questions, you can join the following group chats for consultation, or you can also post &lt;a href="https://github.com/alovajs/alova/discussions" rel="noopener noreferrer"&gt;Discussions in the github repository&lt;/a&gt;. If you encounter problems, please submit them in &lt;a href="https://github.com/alovajs/alova/issues" rel="noopener noreferrer"&gt;github  issues&lt;/a&gt;, and we will solve them in the fastest time.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;a href="https://discord.gg/S47QGJgkVb" rel="noopener noreferrer"&gt;Join the Discord community&lt;/a&gt; &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We also welcome you to contribute your strength, please go to the &lt;a href="https://alova.js.org/contributing/overview" rel="noopener noreferrer"&gt;Contribution Guide&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>programming</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>react-query swrjs alova In-Depth Comparison</title>
      <dc:creator>Scott Hu</dc:creator>
      <pubDate>Sat, 31 Aug 2024 08:03:29 +0000</pubDate>
      <link>https://dev.to/coderhu/in-depth-comparison-how-to-choose-the-most-suitable-enhanced-request-library-2p29</link>
      <guid>https://dev.to/coderhu/in-depth-comparison-how-to-choose-the-most-suitable-enhanced-request-library-2p29</guid>
      <description>&lt;p&gt;As our projects become increasingly complex, users are demanding higher speed and better user experiences. Relying solely on traditional request libraries like Axios or Fetch to handle data requests often results in a lot of redundant boilerplate code, which has long been criticized. This is where enhanced request libraries come into play.&lt;/p&gt;

&lt;p&gt;Some of you might be wondering, "What exactly is an enhanced request library?" An enhanced request library typically builds on top of traditional request libraries and integrates deeply with UI frameworks like React and Vue through hooks. It also provides additional performance optimization features, such as response caching, to help reduce boilerplate code and improve request performance.&lt;/p&gt;

&lt;p&gt;Currently, some of the most popular enhanced request libraries include &lt;code&gt;@tanstack/react-query&lt;/code&gt;, &lt;code&gt;swr&lt;/code&gt;, and the rising star &lt;code&gt;alova&lt;/code&gt;. Each has its unique features. Here, we'll take a deep dive into comparing them to help you determine which one best suits your project's needs. That way, when a new project requirement arises, you'll know exactly which tool to choose.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Quick channel for comparison tools&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://tanstack.com/query" rel="noopener noreferrer"&gt;@tanstack/react-query&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://swr.vercel.app" rel="noopener noreferrer"&gt;swr&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://alova.js.org" rel="noopener noreferrer"&gt;alova&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let's start right now and compare them from the following 8 perspectives.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Product positioning and features&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;hooks&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Framework support&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Server support&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Request method&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Cache strategy&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;API automation solution&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Performance&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Comparison of Positioning and Features
&lt;/h2&gt;

&lt;p&gt;First, let's discuss their different positioning.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;@tanstack/react-query&lt;/strong&gt; primarily focuses on managing asynchronous state. Its strength lies in helping you handle data fetching, caching, and synchronization. When you need data, it fetches it for you; when the data becomes stale, it updates it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;swr&lt;/strong&gt; also focuses on asynchronous state management, using lightweight hooks to simplify data fetching.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;alova&lt;/strong&gt; provides a comprehensive request solution, mainly to help developers raise API integration efficiency. It reduces the number of steps for developers to use API from 7 to just 1, helping developers reduce a lot of API maintenance time.&lt;/p&gt;

&lt;p&gt;Different positioning means these libraries have different design considerations. &lt;code&gt;react-query&lt;/code&gt; and &lt;code&gt;swr&lt;/code&gt; focus mainly on the hooks they provide and cache management functions. In contrast, &lt;code&gt;alova&lt;/code&gt; optimizes API consumption efficiency by taking a more holistic approach to the request strategy. It not only offers hooks but also includes hook middleware, global seamless refresh interceptors, and other features referred to as request strategies. It also provides automatic API generation and search extension plugins. Because of this, I believe &lt;code&gt;alova&lt;/code&gt; addresses API-related challenges in multiple aspects.&lt;/p&gt;

&lt;p&gt;Let's look at a comparative example in React.&lt;/p&gt;

&lt;h3&gt;
  
  
  react-query
&lt;/h3&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useQuery&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@tanstack/react-query&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;fetchUsers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://api.example.com/users&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;UserList&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;users&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;isLoading&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useQuery&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;users&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;fetchUsers&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;isLoading&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Loading...&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;;&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;An error occurred: &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;;&lt;/span&gt;

  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;ul&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;users&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;li&lt;/span&gt; &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;li&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;ul&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;UserList&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h3&gt;
  
  
  swr
&lt;/h3&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;useSWR&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;swr&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;fetcher&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;url&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;UserList&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;users&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useSWR&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://api.example.com/users&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;fetcher&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;users&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Loading...&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;;&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;An error occurred: &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;;&lt;/span&gt;

  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;ul&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;users&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;li&lt;/span&gt; &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;li&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;ul&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;UserList&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h3&gt;
  
  
  alova
&lt;/h3&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;createAlova&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;useRequest&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;alova&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;adapterFetch&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;alova/fetch&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;ReactHook&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;alova/react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;alovaInstance&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;createAlova&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;baseURL&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://api.example.com&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;statesHook&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ReactHook&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;requestAdapter&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;adapterFetch&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;UserList&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;methodInstance&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;alovaInstance&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/users&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;loading&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;users&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useRequest&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;methodInstance&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;loading&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Loading...&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;;&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;An error occurred: &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;;&lt;/span&gt;

  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;ul&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;users&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;li&lt;/span&gt; &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;li&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;ul&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;UserList&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;You can see. &lt;code&gt;react-query&lt;/code&gt;and&lt;code&gt;swr&lt;/code&gt;send requests directly with asynchronous functions, while&lt;code&gt;alova&lt;/code&gt;needs to create a request instance in advance, which defines how to send requests using the fetch adapter under react. In addition, adapters such as&lt;code&gt;xmlhttprequest&lt;/code&gt;and&lt;code&gt;axios&lt;/code&gt; are also provided. These are all due to their positioning-dominated design concepts, and these differences will be reflected in the following comparisons.&lt;/p&gt;

&lt;h2&gt;
  
  
  Comparison of hooks
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Number of hooks
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;@tanstack/react-query&lt;/strong&gt; provides hooks such as &lt;code&gt;useQuery&lt;/code&gt;, &lt;code&gt;useMutation&lt;/code&gt;, and &lt;code&gt;useInfiniteQuery&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;swr&lt;/strong&gt; mainly provides hooks such as &lt;code&gt;useSWR&lt;/code&gt; and &lt;code&gt;useSWRInfinite&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;alova&lt;/strong&gt; provides a total of 15+ request strategies in different request scenarios, including &lt;code&gt;useRequest&lt;/code&gt;, &lt;code&gt;useWatcher&lt;/code&gt;, &lt;code&gt;usePagination&lt;/code&gt;, &lt;code&gt;useFetcher&lt;/code&gt;, &lt;code&gt;useForm&lt;/code&gt;, etc.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  hook actions
&lt;/h3&gt;

&lt;p&gt;One of the features of alova's hooks is that its scenario-based hooks also provide a wealth of actions, which allow developers to more finely control data operations and quickly implement the comprehensive functionality of different complex requests, which is not available in &lt;code&gt;react-query&lt;/code&gt; and &lt;code&gt;swr&lt;/code&gt;. For example, the following is actions for paging request.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;usePagination&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;useForm&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;alova/client&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// Pagination request example&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;loading&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;pageSize&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;pageCount&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;total&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;insert&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;remove&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;refresh&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;reload&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;usePagination&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;pageSize&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;getUserList&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;pageSize&lt;/span&gt; &lt;span class="p"&gt;}),&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;initialPage&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;initialPageSize&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="c1"&gt;// Use actions&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;handleAddUser&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;newUser&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;insert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;newUser&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;handleRemoveUser&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;userId&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;remove&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;userId&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h3&gt;
  
  
  hooks middleware support
&lt;/h3&gt;

&lt;p&gt;alova and swr's hooks support middleware, allowing more fine-grained customization during the request process. But &lt;code&gt;react-query&lt;/code&gt; does not support it.&lt;/p&gt;
&lt;h3&gt;
  
  
  swr
&lt;/h3&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;myMiddleware&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;useSWRNext&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;fetcher&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="c1"&gt;// Before hook runs...&lt;/span&gt;

&lt;span class="c1"&gt;// Process the next middleware, or the `useSWR` hook if this is the last one.&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;swr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useSWRNext&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;fetcher&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;// After the hook runs...&lt;/span&gt;
&lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;swr&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;SWRConfig&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{{&lt;/span&gt; &lt;span class="na"&gt;use&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;myMiddleware&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;}}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;

&lt;span class="c1"&gt;// Or...&lt;/span&gt;

&lt;span class="nf"&gt;useSWR&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;fetcher&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;use&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;myMiddleware&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h3&gt;
  
  
  alova
&lt;/h3&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useRequest&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;alova/client&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// Define a middleware&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;loggingMiddleware&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;context&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;next&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Request started:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;next&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Request ended:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="c1"&gt;// Use middleware in hook&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;loading&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useRequest&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;getUserList&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;middleware&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;loggingMiddleware&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h2&gt;
  
  
  Framework support
&lt;/h2&gt;
&lt;h3&gt;
  
  
  Client
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;@tanstack/react-query&lt;/strong&gt; supports mainstream UI frameworks in the form of independent packages, although it was originally designed for React.&lt;/li&gt;
&lt;/ul&gt;

&lt;ol&gt;
&lt;li&gt;react: &lt;code&gt;@tanstack/react-query&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;vue: &lt;code&gt;@tanstack/vue-query&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;svelte: &lt;code&gt;@tanstack/svelte-query&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;angular: &lt;code&gt;@tanstack/angular-query&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;solid: &lt;code&gt;@tanstack/solid-query&lt;/code&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;swr&lt;/strong&gt; only supports react.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;alova&lt;/strong&gt; supports frameworks such as &lt;code&gt;react/vue/svelte&lt;/code&gt; with a single package + UI framework adapter, unifying the user experience under each UI framework.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  SSR
&lt;/h3&gt;

&lt;p&gt;All three support mainstream SSR frameworks.&lt;/p&gt;
&lt;h2&gt;
  
  
  Server support
&lt;/h2&gt;

&lt;p&gt;@tanstack/react-query and swr mainly provide clienthooks for client applications. Although they can be used in a server-side rendering (SSR) environment, they cannot be used directly in a non-SSR server-side environment, but they do not provide APIs used in pure server-side environments (such as Express or Koa route handlers).&lt;/p&gt;

&lt;p&gt;In contrast, alova not only fully supports server-side programs, but also provides server-side request strategies for the server-side environment. They are called &lt;strong&gt;server hooks&lt;/strong&gt;, which makes it easier and more flexible to control requests on the server side.&lt;/p&gt;

&lt;p&gt;The following is an example of sending a verification code with retry:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;retry&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;sendCaptcha&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;alova/server&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/api/captcha/send&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;email&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;email&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="c1"&gt;// Create a method instance for sending a verification code&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;captchaMethod&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;alovaInstance&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/api/captcha&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;email&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;captcha content&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="c1"&gt;// Use retry hook to wrap captchaMethod&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;retringMethod&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;retry&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;captchaMethod&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;retry&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;backoff&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;delay&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="c1"&gt;// Use sendCaptcha hook to wrap retringMethod, and send the request and get the response result through await&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;sendCaptcha&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;retringMethod&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;email&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h2&gt;
  
  
  Request method
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;@tanstack/react-query&lt;/code&gt; and &lt;code&gt;swr&lt;/code&gt; provide asynchronous functions to receive request data. Users need to directly use &lt;code&gt;axios&lt;/code&gt; or &lt;code&gt;fetch&lt;/code&gt; third-party request libraries to obtain data and provide it to &lt;code&gt;@tanstack/react-query&lt;/code&gt; and &lt;code&gt;swr&lt;/code&gt;. This gives all control of the request to the user, and even simulates the request in the asynchronous function.&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;fetchUsers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;
  &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;setTimeout&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nf"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;your data&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;users&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;isLoading&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useQuery&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;users&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;fetchUsers&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;But &lt;code&gt;alova&lt;/code&gt; uses Method as a proxy object, which has the following advantages for me:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Provides a unified request method. Users do not need to care about what method is used for request except setting the request adapter.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;It has various uses. Users can use Method to send requests directly like axios, and can also directly pass it into hooks to control requests.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;

&lt;span class="c1"&gt;// Direct request&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;alvoaInstance&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/users&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// Pass in request in useRequest&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;loading&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useRequest&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;alvoaInstance&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/users&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;For example, using &lt;code&gt;XMLHttpRequest&lt;/code&gt; request can also get a complete and unified experience, including global interceptors. Alova provides &lt;code&gt;XMLHttpRequest&lt;/code&gt; adapter, but it needs to be encapsulated in &lt;code&gt;@tanstack/react-query&lt;/code&gt; and &lt;code&gt;swr&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Easy to port to other projects, just change the request interceptor globally.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Cache strategy
&lt;/h2&gt;

&lt;h3&gt;
  
  
  @tanstack/react-query
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Fine cache control&lt;/strong&gt;: &lt;code&gt;@tanstack/react-query&lt;/code&gt; allows to configure &lt;code&gt;staleTime&lt;/code&gt; and &lt;code&gt;cacheTime&lt;/code&gt; to determine the cache duration and expiration time of data.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Automatic refresh and invalidation&lt;/strong&gt;: Configure automatic refresh of data under certain conditions through options such as &lt;code&gt;refetchOnWindowFocus&lt;/code&gt; and &lt;code&gt;refetchOnReconnect&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Cache data persistence&lt;/strong&gt;: Implement persistent storage of client cache data through the &lt;code&gt;persistQueryClient&lt;/code&gt; plugin.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Cache debugging tool&lt;/strong&gt;: Provides &lt;code&gt;ReactQueryDevtools&lt;/code&gt; debugging tool for observing and processing data requests and cache status.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  swr
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Custom global cache&lt;/strong&gt;: SWR uses a global cache to share data, and allows customizing how to store cache through the &lt;code&gt;provider&lt;/code&gt; option of &lt;code&gt;SWRConfig&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Modify cache data&lt;/strong&gt;: Provides &lt;code&gt;mutate&lt;/code&gt; function to modify the cache, including clearing all cached data or updating specific cache items.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cache debugging tool&lt;/strong&gt;: View and debug through browser extensions.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  alova
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Multi-level cache&lt;/strong&gt;: Supports L1 and L2 multi-level cache, and can restore data from persistent storage after the memory cache is invalidated to adapt to different usage scenarios.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Fine cache control&lt;/strong&gt;: Allows you to set different expiration times for different levels of cache, providing more flexible cache management.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Automatic cache invalidation&lt;/strong&gt;: Automatically invalidate the corresponding cache by specifying the relationship between APIs, reducing the trouble of manual invalidation.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Flexible cache storage&lt;/strong&gt;: You can use any cache storage to store data, such as &lt;code&gt;localStorage&lt;/code&gt;, &lt;code&gt;sessionStorage&lt;/code&gt;, &lt;code&gt;indexedDB&lt;/code&gt; on the client, &lt;code&gt;AsyncStorage&lt;/code&gt; under react-native, and &lt;code&gt;@alova/psc&lt;/code&gt; shared by multiple processes on the server, or even redis storage shared by clusters.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  API Automation Solution
&lt;/h2&gt;

&lt;p&gt;Since &lt;code&gt;@tanstack/react-query&lt;/code&gt; and &lt;code&gt;swr&lt;/code&gt; give all control of the request to the user, the API automation solution is provided by third-party request tools. For example, &lt;code&gt;axios&lt;/code&gt; and &lt;code&gt;fetch&lt;/code&gt; can automatically generate request codes through &lt;a href="https://github.com/OpenAPITools/openapi-generator" rel="noopener noreferrer"&gt;openapi-generator&lt;/a&gt; or &lt;a href="https://github.com/OpenAPITools/openapi-generator-cli" rel="noopener noreferrer"&gt;@openapitools/openapi-generator-cli&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Alova provides a more advanced openAPI solution. , including the following:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Generate API call code, TypeScript type and detailed API documentation for each API at the same time, so that you can enjoy complete API type hints even in JavaScript projects, which are not available in &lt;code&gt;openapi-generator&lt;/code&gt; and &lt;code&gt;@openapitools/openapi-generator-cli&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;A brand new API integration experience. In the past, when the backend developer delivered the API to you, you needed to open the intermediate API document to query and copy key information to your project. You needed to constantly switch between the API document and the editor in the middle, but now, Alova's development tools can eliminate the intermediate API document for you, shortening the collaboration distance between the front and back ends like a wormhole. Through it, you can quickly find the required API in the editor and display the complete documentation of this API, and quickly complete parameter transfer by referring to the API parameter table.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fb6rahb7z7biltibovn4k.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fb6rahb7z7biltibovn4k.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Update the API regularly and actively notify the front-end development, no longer relying on the notification of the server-side developer.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Performance
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Dependency collection
&lt;/h3&gt;

&lt;p&gt;Dependency collection refers to the automatic tracking of the status of component dependencies within hooks. When the status of the dependency changes, it will trigger the re-rendering of the view. This is more of a way to reduce the rendering of react components.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;swr&lt;/code&gt; and &lt;code&gt;alova&lt;/code&gt; both support dependency collection, while &lt;code&gt;@tanstack/react-query&lt;/code&gt; does not.&lt;/p&gt;

&lt;h3&gt;
  
  
  Alova's unique performance features
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Request sharing
&lt;/h4&gt;

&lt;p&gt;Request sharing means that when multiple identical requests are issued at the same time, only one request will be actually issued, and the response data will be shared with these requests. It can not only improve the fluency of the application, but also reduce the pressure on the server.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqwl093uwd1kju7sv8oq0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqwl093uwd1kju7sv8oq0.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;@tanstack/react-query&lt;/code&gt; and &lt;code&gt;swr&lt;/code&gt; are not supported, &lt;code&gt;alova&lt;/code&gt; is supported on both the client and the server.&lt;/p&gt;

&lt;h4&gt;
  
  
  hooks performance optimization
&lt;/h4&gt;

&lt;p&gt;Compared with &lt;code&gt;@tanstack/react-query&lt;/code&gt; and &lt;code&gt;swr&lt;/code&gt; hooks, one feature of alova's scenario-based hooks is that it can optimize performance for specific scenarios, for example:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;usePagination&lt;/code&gt; can automatically pre-fetch the list data of the previous and next pages, so that users do not need to wait when turning pages (turning pages in seconds)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;useForm&lt;/code&gt; provides a form draft, and unsubmitted data will not be deleted even if it is refreshed&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h4&gt;
  
  
  Default GET cache
&lt;/h4&gt;

&lt;p&gt;Since alova's cache key is automatically calculated through the request information of the method instance, by default, alova's GET has a 5-minute cache, and there is no need to repeat the request when multiple requests for duplicate data are made.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;After an in-depth discussion, we have a more comprehensive understanding of the three request enhancement libraries &lt;code&gt;alova&lt;/code&gt;, &lt;code&gt;@tanstack/react-query&lt;/code&gt; and &lt;code&gt;swr&lt;/code&gt;. Each library has its own unique advantages and applicable scenarios. Which library to choose ultimately depends on your project requirements, the team's technology stack, and considerations of performance, ease of use, and flexibility.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;swr is known for its simplicity and ease of use. If you are looking for a lightweight and easy-to-use solution, or your project focuses on fast rendering and minimizing server requests, srw will be an ideal choice.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;For applications that require powerful state management and caching capabilities, &lt;code&gt;@tanstack/react-query&lt;/code&gt; is a good choice.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If you don't want to spend more time on API use, want to find a unified request solution, or are sending requests in Express or koa, alova may be more suitable for your needs.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;There is no best library, only the one that best suits your project. Take the time to evaluate and compare different tools, and finally choose the one that can help you and your team work more efficiently and happily.&lt;/p&gt;

&lt;p&gt;I hope this article can help you better understand the characteristics of these three request enhancement libraries and make wise choices in actual projects.&lt;/p&gt;

&lt;p&gt;Bye everyone!!!&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>swr</category>
      <category>reactquery</category>
    </item>
    <item>
      <title>3 months later, I optimized request code generation to the extreme</title>
      <dc:creator>Scott Hu</dc:creator>
      <pubDate>Fri, 28 Jun 2024 04:24:53 +0000</pubDate>
      <link>https://dev.to/coderhu/3-months-later-i-optimized-request-code-generation-to-the-extreme-4m9j</link>
      <guid>https://dev.to/coderhu/3-months-later-i-optimized-request-code-generation-to-the-extreme-4m9j</guid>
      <description>&lt;p&gt;Have you ever heard of the automatic request code generation solution? Yes, that's right, it's generated by the openapi specification, and I always feel that something is missing.&lt;/p&gt;

&lt;p&gt;After 3 months of research, I have simplified the front-end and back-end collaboration process into one step!&lt;/p&gt;

&lt;p&gt;Usually, the front-end and back-end collaboration is a tedious task. Usually we may have such a process:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;The back-end notifies the front-end "xxx interface is ready"&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;First look through the api document to find the newly added api&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Go back to your own code and define all new api call functions&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If you use TS, you have to add type definitions manually&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;In different pages, select the corresponding api call function&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Introduce the call function&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Write complex call logic, such as paging and controlling the page number parameter&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;We have removed all the 123467 above, and even eliminated the intermediate api document link, allowing you to check and call the api in the editor, which may change your future development method.&lt;/p&gt;

&lt;p&gt;Let me explain it in detail.&lt;/p&gt;

&lt;h2&gt;
  
  
  Automatic generation
&lt;/h2&gt;

&lt;p&gt;Automatically generating API call code according to the openapi specification should be a commonplace, and my solution is to use the VSCode plug-in. Whether you use ESModule, CommonJS or TypeScript, click the generate button in the lower right corner of the editor, it will automatically generate the corresponding standard interface call code and the corresponding response type according to the project type. Whether in js or ts projects, you can experience the complete code prompt function.&lt;/p&gt;


&lt;div class="crayons-card c-embed text-styles text-styles--secondary"&gt;
    &lt;a href="https://dev-to-uploads.s3.amazonaws.com/uploads/articles/5z3abeh3eitq9mcz088h.gif" rel="noopener noreferrer"&gt;
      dev-to-uploads.s3.amazonaws.com
    &lt;/a&gt;
&lt;/div&gt;


&lt;p&gt;Generated code Contains the following content:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnujztxlm3k3e3hradgg2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnujztxlm3k3e3hradgg2.png" alt="Image description" width="800" height="349"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;code&gt;apiDefinitions.js&lt;/code&gt; is used to record the generated api path and request method.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;createApis.js&lt;/code&gt; uses proxy to dynamically create call functions based on &lt;code&gt;apiDefinitions.js&lt;/code&gt;, which can reduce a lot of template code.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;globals.d.ts&lt;/code&gt; provides complete code prompt function.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;index.js&lt;/code&gt; is used for user-defined configuration.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This cuts off step 34 in the process.&lt;/p&gt;

&lt;p&gt;Then we can also set a timer to check the update status of the openapi file. If there is an update, we will immediately remind you to ensure that you always use the latest api definition. This saves the backend partner from notifying you of api updates, and eliminates step 1 in the process.&lt;/p&gt;

&lt;p&gt;Now the process is as follows:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;del&gt;The backend notifies the frontend "xxx interface is ready"&lt;/del&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;First look through the api document to find the newly added api&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;del&gt;Go back to your own code and define all new api call functions&lt;/del&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;del&gt;If you use TS, you have to add type definitions manually&lt;/del&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;In different pages, select the corresponding api call function&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Introduce the call function&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Write complex call logic, such as paging and controlling the number of pages&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Check and use the API in the editor
&lt;/h2&gt;

&lt;p&gt;In order to eliminate step 2, we really racked our brains, so let's just move the api document to the editor and copy the parameters according to the description when you use the interface.&lt;/p&gt;

&lt;p&gt;The following is a demonstration of a js project without any additional configuration.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7y8zayhsyz23amxxkbfw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7y8zayhsyz23amxxkbfw.png" alt="Image description" width="610" height="364"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Access the interface through the global &lt;code&gt;Apis&lt;/code&gt;, reference &lt;code&gt;src/api/index&lt;/code&gt; in the entry file, and then you can directly access it everywhere, which eliminates step 7 again, and the editor's smart prompt displays all the information of the current api.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fuc68yrbl16o9pt4tx2vp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fuc68yrbl16o9pt4tx2vp.png" alt="Image description" width="800" height="487"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can also see the prompts and descriptions of the parameters when filling in the parameters.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9in25jfyjylqrdgdmm25.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9in25jfyjylqrdgdmm25.png" alt="Image description" width="800" height="492"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The response data prompt is as follows.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsbz78p4g3j9e6ms12p4z.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsbz78p4g3j9e6ms12p4z.png" alt="Image description" width="800" height="416"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Find API through path
&lt;/h3&gt;

&lt;p&gt;What is this? I don't know what the specific reference name is? It doesn't matter, you can also find it by using the API call path:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fh0c091m5yqp95x4anjtz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fh0c091m5yqp95x4anjtz.png" alt="Image description" width="800" height="189"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Find the API by description
&lt;/h3&gt;

&lt;p&gt;Really can't remember anything? Then search using the keywords in the API description:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F24ru58vahi5ou4l0ph9s.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F24ru58vahi5ou4l0ph9s.png" alt="Image description" width="800" height="173"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;At this point, steps 2 and 6 are also done:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;del&gt;The backend notifies the frontend that "xxx interface is ready"&lt;/del&gt;&lt;/li&gt;
&lt;li&gt;&lt;del&gt;First look through the api document to find the newly added api&lt;/del&gt;&lt;/li&gt;
&lt;li&gt;&lt;del&gt;Go back to your own code and define all new api call functions&lt;/del&gt;&lt;/li&gt;
&lt;li&gt;&lt;del&gt;If you use TS, you have to add type definitions manually&lt;/del&gt;&lt;/li&gt;
&lt;li&gt;In different pages, select the corresponding api call function&lt;/li&gt;
&lt;li&gt;&lt;del&gt;Introduce calling function&lt;/del&gt;&lt;/li&gt;
&lt;li&gt;Write complex calling logic, for example, paging also needs to control the number of pages&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Request strategy modules
&lt;/h2&gt;

&lt;p&gt;How to solve step 7? Of course, encapsulate the calling logic according to different usage scenarios. Although there seem to be many scenarios, let's encapsulate the commonly used ones first, so there are the following encapsulations, which we call "request strategy module" because it is not only encapsulation, but also many performance optimizations.&lt;/p&gt;

&lt;p&gt;Here are some simple examples, such as paging request:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;loading&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;pageSize&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;total&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;usePagination&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;size&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;
    &lt;span class="nx"&gt;alova&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/api/user/list&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;params&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;size&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Form submission:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// Submission status&lt;/span&gt;
  &lt;span class="na"&gt;loading&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;submiting&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="c1"&gt;// Responsive form data&lt;/span&gt;
  &lt;span class="nx"&gt;form&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="c1"&gt;// Submission data function&lt;/span&gt;
  &lt;span class="na"&gt;send&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;submit&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useForm&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;formData&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;formSubmit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;formData&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// Initialize form data&lt;/span&gt;
  &lt;span class="na"&gt;initialForm&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;cls&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;1&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Monitor request:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;loading&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useWatcher&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="c1"&gt;// State change will trigger this function once&lt;/span&gt;
  &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;filterTodoList&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;userId&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;

  &lt;span class="c1"&gt;// Array of monitored states&lt;/span&gt;
  &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;userId&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, it is finally simplified to only one step.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;del&gt;The backend notifies the frontend that "xxx interface is ready"&lt;/del&gt;&lt;/li&gt;
&lt;li&gt;&lt;del&gt;First look through the api document to find the newly added api&lt;/del&gt;&lt;/li&gt;
&lt;li&gt;&lt;del&gt;Go back to your own code and define the call function for all new apis&lt;/del&gt;&lt;/li&gt;
&lt;li&gt;&lt;del&gt;If you use TS, you have to add type definitions manually&lt;/del&gt;&lt;/li&gt;
&lt;li&gt;In different pages, select the corresponding api call function&lt;/li&gt;
&lt;li&gt;&lt;del&gt;Introduce the call function&lt;/del&gt;&lt;/li&gt;
&lt;li&gt;&lt;del&gt;Write complex call logic, such as paging and controlling the number of pages&lt;/del&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  The last easter eggs
&lt;/h2&gt;

&lt;p&gt;At this point, I believe you have already felt the convenience of this plug-in, right? This is actually a VSCode plug-in tailored for alova!&lt;/p&gt;

&lt;p&gt;Our easter egg is that alova has finally ushered in a major upgrade to 3.0, redesigning the underlying architecture and comprehensively refactoring. Now it can be used completely in the client and server. In addition, in order to make it easier to use, this upgrade has abandoned 10 configurations and 9 optimizations. If you think alova is good, please &lt;a href="https://github.com/alovajs/alova/tree/next"&gt;star us on Github&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Visit the official website of alovajs for more details: &lt;a href="https://alova.js.org"&gt;alovajs official website&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;And this plug-in is not just an ordinary development tool, but it maximizes the convenience of alova. Through this plug-in, we have brought the user experience of alova to a whole new level, truly realizing the goal of "as simple as calling a local function".&lt;/p&gt;

&lt;p&gt;However, our team is now conducting the final optimization and testing of this plug-in, which will be released in the near future. Good things are always worth waiting for. You are also welcome to tell us your thoughts, complaints or suggestions in the comment area.&lt;/p&gt;

&lt;p&gt;If you are an alova user, or are interested in experiencing our project, you can join our WeChat group to get the latest progress at the first time, and you can also communicate directly with the development team and put forward your ideas and suggestions.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://discord.gg/S47QGJgkVb"&gt;Join the Discord&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;After joining the communication community, you will get:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The latest news about plugins and alova&lt;/li&gt;
&lt;li&gt;Exchange usage experience with other developers&lt;/li&gt;
&lt;li&gt;Make suggestions or feedback directly to the development team&lt;/li&gt;
&lt;li&gt;Possible internal testing opportunities&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;If you have any questions, you can join the following group chat for consultation, or post Discussions in the &lt;a href="https://github.com/alovajs/alova/discussions"&gt;github repository&lt;/a&gt;. If you encounter any problems, please submit them in &lt;a href="https://github.com/alovajs/alova/issues"&gt;github issues&lt;/a&gt;, and we will solve them as soon as possible.&lt;/p&gt;

&lt;p&gt;You are also welcome to contribute. Please go to the &lt;a href="https://alova.js.org/contributing/overview"&gt;Contribution Guide&lt;/a&gt;&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>openapi</category>
      <category>alova</category>
      <category>axios</category>
    </item>
    <item>
      <title>The next generation request library alova has received a major upgrade, making it easier to use and higher in performance.</title>
      <dc:creator>Scott Hu</dc:creator>
      <pubDate>Fri, 10 May 2024 03:09:26 +0000</pubDate>
      <link>https://dev.to/coderhu/the-next-generation-request-library-alova-has-received-a-major-upgrade-making-it-easier-to-use-and-higher-in-performance-5efj</link>
      <guid>https://dev.to/coderhu/the-next-generation-request-library-alova-has-received-a-major-upgrade-making-it-easier-to-use-and-higher-in-performance-5efj</guid>
      <description>&lt;p&gt;hello!&lt;/p&gt;

&lt;p&gt;Maybe you have also heard of alova, a lightweight request library, which can help you implement complex data requests at a lower cost, saving developers energy and time.&lt;/p&gt;

&lt;p&gt;If you need to learn about alova, you can &lt;a href="https://alova.js.org"&gt;visit the official website&lt;/a&gt;, where you can find more detailed documentation and sample code to help you better understand and use this tool.&lt;/p&gt;

&lt;p&gt;It has been a year since the release of alova2.0. During this period, it has received a lot of praise. Of course, it has also received a lot of feedback for improvements, which has made alova continue to mature and improve. I am very grateful to everyone who has contributed to alova, and I also know it. There are many redundancies and flaws in the design.&lt;/p&gt;

&lt;p&gt;Now, in order to better serve you, it is time to upgrade to 3.0. The purpose of this upgrade mainly focuses on the following goals:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Adjust alova structure and expand application scope&lt;/li&gt;
&lt;li&gt;Simplify usage, discard unnecessary APIs, and adjust defective designs.&lt;/li&gt;
&lt;li&gt;Redesign some modules to improve performance&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Before looking at the specific 3.0 adjustments, let us review what exactly alova is going to do and where it is going.&lt;/p&gt;

&lt;h2&gt;
  
  
  Pain points of network requests
&lt;/h2&gt;

&lt;p&gt;In enterprise-level projects involving multi-person collaboration, the cost of Client-Server interaction is relatively high.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1w2wwhzr93xi2a8vgw73.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1w2wwhzr93xi2a8vgw73.png" alt="pain points of requests" width="800" height="274"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;High cost of front-end and back-end collaboration&lt;/strong&gt;:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Depends on backend notification&lt;/strong&gt;: API updates require active notification from the backend&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;API document dependence&lt;/strong&gt;: The front end needs to consult the API document to obtain information.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;API code writing&lt;/strong&gt;: The front-end manually writes the interface code according to the API document.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Lack of response data type&lt;/strong&gt;: API response data does not have type hints by default, which increases the cost of data usage.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Increase in bug rate&lt;/strong&gt;: API changes may lead to an increase in the bug rate of the project.&lt;/li&gt;
&lt;/ol&gt;


&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Complex data interaction logic&lt;/strong&gt;: Front-end requests are often not that simple. You need to consider when to send requests, when not to send requests, how to process response data, etc. according to different scenarios to meet the performance and performance improvement of the project. This will result in increased developer time costs and code maintenance costs.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  solution
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzlit7lv879dsv1b34uef.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzlit7lv879dsv1b34uef.png" alt="solution" width="800" height="320"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;IDE plug-in (vscode/webStorm)&lt;/strong&gt;: Solve the problem of front-end and back-end collaboration (specific solutions can be viewed in the Feishu document below)&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Automatically generate request codes and response data types&lt;/li&gt;
&lt;li&gt;Embed the api document into the code, you can directly query and insert the API interface in the code&lt;/li&gt;
&lt;li&gt;Update API information regularly and proactively notify front-end development&lt;/li&gt;
&lt;li&gt;Interface update records to prevent changes from causing bugs&lt;/li&gt;
&lt;/ol&gt;


&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Request Strategy&lt;/strong&gt;: Select the corresponding request strategy and implement complex data interaction logic in one line of code.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  alova goals
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Don't spend time on the small matter of requesting, leave it to alova&lt;/strong&gt;, it will save you most of the work in requesting, you only need to specify which API to use and what strategy to execute the request. .&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;a href="mailto:alova@3.0"&gt;alova@3.0&lt;/a&gt; update plan
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Release Notes
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;Before the official version 3.0 is released, we always welcome your feedback. You are welcome to comment in the article or submit your valuable opinions on WeChat from any angle such as usage scenarios and design issues.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The specific update content, progress, and IDE plug-in design can be viewed in &lt;a href="https://maple-mastodon-428.notion.site/Alova-Product-White-Paper-and-3-0-Update-Overview-02f0a713bf7d46e1be5a69db4981217c?pvs=4"&gt;alova product white paper and 3.0 update overview&lt;/a&gt;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://discord.gg/S47QGJgkVb"&gt;Join the Discord community to participate in communication&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Find core partner people
&lt;/h2&gt;

&lt;p&gt;alovajs has so far achieved certain feasibility verification. In order to speed up its development, it is now necessary to invite two friends who agree with alovajs to join the core team (one has been confirmed) to be responsible for the core work of alovajs. This may allow you to obtain huge benefits. Friends who are willing to learn more see &lt;a href="https://alova.js.org/contributing/become-core-member"&gt;Become a Core Member&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>alova</category>
      <category>react</category>
      <category>vue</category>
    </item>
    <item>
      <title>Quickly implement senseless refresh token</title>
      <dc:creator>Scott Hu</dc:creator>
      <pubDate>Fri, 19 Jan 2024 05:43:38 +0000</pubDate>
      <link>https://dev.to/coderhu/quickly-implement-senseless-refresh-token-269c</link>
      <guid>https://dev.to/coderhu/quickly-implement-senseless-refresh-token-269c</guid>
      <description>&lt;p&gt;Some time ago, Alova users frequently received feedback on how to implement a senseless token refresh function like Axios. This is indeed troublesome, and I believe everyone has a deep understanding of it.&lt;/p&gt;

&lt;p&gt;It really depresses me to have to repeat it every time. So out of anger, I decided to write a universal token authentication module so that alova users would no longer have to worry about this matter.&lt;/p&gt;

&lt;p&gt;Using alova's Token authentication interceptor can perfectly solve the following problems for you:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Unify and maintain all codes for token identity authentication, including login, logout, token attachment, token refresh, etc.;&lt;/li&gt;
&lt;li&gt;Supports verification of token expiration on the client and server, and refreshes the token without any warning;&lt;/li&gt;
&lt;li&gt;Requests that rely on tokens automatically wait for the token refresh to complete before requesting;&lt;/li&gt;
&lt;li&gt;Automatically release visitor requests that do not rely on tokens;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The only thing you have to do is configure the role type of the request interface, and then the rest will be automatically taken care of for you.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Some people may not know it. To give a brief introduction, alova is a request strategy library. Its usage is similar to axios, but you can implement complex requests such as request sharing, paging request, form submission, and breakpoint resume by simply configuring parameters. Etc., there is no need to write a lot of code, improve development efficiency, application performance, and reduce server pressure.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The Token identity authentication module is one of alova's request modules. It is completed through a global interceptor and provides client- and server-based identity authentication respectively.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Client-based identity authentication: means judging whether the token has expired from the client, such as the token expiration time obtained during login;&lt;/li&gt;
&lt;li&gt;Server-based identity authentication: It indicates whether the token has expired based on the status returned from the server. For example, when &lt;code&gt;status&lt;/code&gt; is 401, it means it has expired;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Next, let’s talk about server-based identity authentication as an example.&lt;/p&gt;

&lt;h2&gt;
  
  
  Install the dependencies first
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;#vue&lt;/span&gt;
npm &lt;span class="nb"&gt;install &lt;/span&gt;alova @alova/scene-vue &lt;span class="nt"&gt;--save&lt;/span&gt;
&lt;span class="c"&gt;# react&lt;/span&gt;
npm &lt;span class="nb"&gt;install &lt;/span&gt;alova @alova/scene-react &lt;span class="nt"&gt;--save&lt;/span&gt;
&lt;span class="c"&gt;#svelte&lt;/span&gt;
npm &lt;span class="nb"&gt;install &lt;/span&gt;alova @alova/scene-svelte &lt;span class="nt"&gt;--save&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Implement nonsensical refresh Token on the server side
&lt;/h2&gt;

&lt;p&gt;When the status returned by the server is that the token has expired (for example, 401), it means that the token needs to be refreshed. At this time, requests initiated during the refresh process will also be waiting.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;onAuthRequired&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;onResponseRefreshToken&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;createServerTokenAuthentication&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
   &lt;span class="na"&gt;refreshTokenOnSuccess&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
     &lt;span class="c1"&gt;// Triggered when responding, the response and method can be obtained, and a boolean is returned to indicate whether the token has expired.&lt;/span&gt;
     &lt;span class="c1"&gt;// When the server returns 401, it means the token has expired.&lt;/span&gt;
     &lt;span class="na"&gt;isExpired&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
       &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;status&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="mi"&gt;401&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
     &lt;span class="p"&gt;},&lt;/span&gt;

     &lt;span class="c1"&gt;// Triggered when the token expires, trigger the refresh token in this function&lt;/span&gt;
     &lt;span class="na"&gt;handler&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;method&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
       &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;token&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;refresh_token&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;refreshToken&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
       &lt;span class="nx"&gt;localStorage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setItem&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;token&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;token&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
       &lt;span class="nx"&gt;localStorage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setItem&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;refresh_token&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;refresh_token&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
     &lt;span class="p"&gt;}&lt;/span&gt;
   &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It will return two interceptor functions, which we can bind to alova's global request interceptor and response interceptor respectively.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;createServerTokenAuthentication&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@alova/scene-*&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;createAlova&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;alova&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;onAuthRequired&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;onResponseRefreshToken&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;createServerTokenAuthentication&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
   &lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;alovaInstance&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;createAlova&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
   &lt;span class="c1"&gt;// ...&lt;/span&gt;
   &lt;span class="na"&gt;beforeRequest&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;onAuthRequired&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;method&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
     &lt;span class="c1"&gt;// ...interceptor before original request&lt;/span&gt;
   &lt;span class="p"&gt;}),&lt;/span&gt;
   &lt;span class="na"&gt;responded&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;onResponseRefreshToken&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;method&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
     &lt;span class="c1"&gt;//...original response success interceptor&lt;/span&gt;
     &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
   &lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Finally, in order to prevent the &lt;code&gt;refreshToken&lt;/code&gt; request from being intercepted, it is necessary to identify &lt;code&gt;authRole&lt;/code&gt; as &lt;code&gt;refreshToken&lt;/code&gt; through metadata.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;For more information about metadata, please go to &lt;a href="https://alova.js.org/tutorial/getting-started/method-metadata"&gt;method metadata&lt;/a&gt;.&lt;br&gt;
&lt;/p&gt;
&lt;/blockquote&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;refreshToken&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;method&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;alovaInstance&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/refresh_token&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
   &lt;span class="nx"&gt;method&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;meta&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
     &lt;span class="na"&gt;authRole&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;refreshToken&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
   &lt;span class="p"&gt;};&lt;/span&gt;
   &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;method&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;In this way, a complete token silent refresh function is completed&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Release visitor request
&lt;/h2&gt;

&lt;p&gt;Some interfaces do not need to rely on token authentication. We call them "guest requests". At this time, we can set their metadata to &lt;code&gt;authRole: null&lt;/code&gt; to bypass the front-end interception and allow them to send requests and receive responses smoothly.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;requestTokenNotRequired&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;method&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;alovaInstance&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/token_not_required&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
   &lt;span class="nx"&gt;method&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;meta&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
     &lt;span class="na"&gt;authRole&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;
   &lt;span class="p"&gt;};&lt;/span&gt;
   &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;method&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  End
&lt;/h2&gt;

&lt;p&gt;In addition, the token authentication request module also provides functions based on client status verification (that is, the front end determines whether the token has expired), login interception, logout interception, etc., making the login authentication function simpler. &lt;a href="https://alova.js.org/tutorial/strategy/tokenAuthentication"&gt;Documentation of token authentication module is here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;If you have any questions, you can join the following group chat for consultation, or you can publish Discussions in &lt;a href="https://github.com/alovajs/alova/discussions"&gt;github repository&lt;/a&gt;. If you encounter problems, please also post in &lt;a href="https://github.com/alovajs/alova/issues"&gt;github issues &lt;/a&gt; and we will solve it as soon as possible.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://discord.gg/S47QGJgkVb"&gt;Join the Discord community to participate in communication&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You are also welcome to contribute, please go to &lt;a href="https://alova.js.org/contributing/overview"&gt;Contribution Guide&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>login</category>
      <category>javascript</category>
      <category>react</category>
      <category>vue</category>
    </item>
    <item>
      <title>Refresh token silently in alovajs</title>
      <dc:creator>Scott Hu</dc:creator>
      <pubDate>Mon, 18 Dec 2023 06:14:59 +0000</pubDate>
      <link>https://dev.to/coderhu/refresh-token-silently-in-alovajs-1h8j</link>
      <guid>https://dev.to/coderhu/refresh-token-silently-in-alovajs-1h8j</guid>
      <description>&lt;p&gt;alova is a lightweight request strategy library designed to simplify the management and use of interfaces. By simply configuring parameters, you can implement complex requests such as sharing requests, paging requests, form submissions, breakpoint resumption, etc., without writing a lot of code, improving development efficiency, application performance, and reducing server pressure.&lt;/p&gt;

&lt;p&gt;When requesting, we often need to authorize login through token, and refresh the token through refresh_token when the token expires. Here we will discuss how to refresh the token without any sense through alova, that is, automatically refresh the token when the token is found to have expired. At the request initiation point It will not feel that the token has been refreshed.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;At present, the token authentication module has been launched. It only requires simple configuration to achieve senseless token refresh. It is recommended to use it directly. &lt;a href="https://alova.js.org/tutorial/strategy/tokenAuthentication"&gt;View details-&amp;gt;&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The following are two ideas for implementing a senseless refresh token. Each idea implements the function of the token to wait for other requests during the refresh period.&lt;/p&gt;

&lt;h2&gt;
  
  
  Determine token expiration on the front end
&lt;/h2&gt;

&lt;p&gt;This is used to determine whether the token has expired at the front end. This is usually used when the token expiration time is returned during login. The idea is to determine whether the token has expired in &lt;code&gt;beforeRequest&lt;/code&gt;. If it has expired, refresh the token first and then continue to send the request. Its advantage is A response with an expired token will not be received, so there is no need to send repeated requests.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;token&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;refreshToken&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;tokenRefreshing&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;waitingList&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[];&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;alovaInstance&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;createAlova&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
   &lt;span class="c1"&gt;// ...&lt;/span&gt;
   &lt;span class="na"&gt;beforeRequest&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nx"&gt;method&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
     &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;getCache&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;token_expire_time&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;method&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;meta&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;authType&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;refreshToken&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="c1"&gt;// token expires&lt;/span&gt;
       &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;tokenRefreshing&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
         &lt;span class="c1"&gt;// If the token is being refreshed, wait for the refresh to complete before sending a request.&lt;/span&gt;
         &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Refreshing token, waiting for request&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
         &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
           &lt;span class="nx"&gt;waitingList&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
         &lt;span class="p"&gt;});&lt;/span&gt;
       &lt;span class="p"&gt;}&lt;/span&gt;

       &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
         &lt;span class="nx"&gt;tokenRefreshing&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
         &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;refreshToken&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;newRefreshToken&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;token&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;newToken&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;tokenRefresh&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;refreshToken&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
         &lt;span class="c1"&gt;//Save the new token and refreshToken&lt;/span&gt;
         &lt;span class="nx"&gt;token&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;newToken&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
         &lt;span class="nx"&gt;refreshToken&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;newRefreshToken&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

         &lt;span class="nx"&gt;tokenRefreshing&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
         &lt;span class="c1"&gt;// After refreshing the token, notify the requests in the waiting list&lt;/span&gt;
         &lt;span class="nx"&gt;waitingList&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
         &lt;span class="nx"&gt;waitingList&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[];&lt;/span&gt;
       &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
         &lt;span class="c1"&gt;// If the refresh token fails, you can handle operations such as jumping to the login interface.&lt;/span&gt;
         &lt;span class="c1"&gt;// ...&lt;/span&gt;
       &lt;span class="p"&gt;}&lt;/span&gt;
     &lt;span class="p"&gt;}&lt;/span&gt;

     &lt;span class="nx"&gt;method&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Authorization&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;token&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
   &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here the tokenRefresh request method adds &lt;code&gt;meta data of&lt;/code&gt;authType = 'refreshToken' as an identifier before the request can pass.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;tokenRefresh&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;method&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;alovaInst&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/refresh-token&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
     &lt;span class="na"&gt;localCache&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;
   &lt;span class="p"&gt;});&lt;/span&gt;
   &lt;span class="nx"&gt;method&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;meta&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
     &lt;span class="na"&gt;authType&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;refreshToken&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
   &lt;span class="p"&gt;};&lt;/span&gt;
   &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;method&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Determine token expiration based on the status returned by the server.
&lt;/h2&gt;

&lt;p&gt;This method is to determine whether the token has expired through the return status of the server. This is usually used when the token expiration time is not returned during login. The idea is to determine whether the token has expired by returning the status in &lt;code&gt;responded.onSuccess&lt;/code&gt;. If it has expired, refresh the token. The advantage of sending the request again is that it is more accurate, but duplicate requests will also be sent.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;token&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;refreshToken&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;tokenRefreshing&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// Refreshing token, let other requests wait first&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;waitingList&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[];&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;alovaInst&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;createAlova&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
   &lt;span class="c1"&gt;// ...&lt;/span&gt;
   &lt;span class="na"&gt;beforeRequest&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;meta&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
     &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Requesting&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
     &lt;span class="c1"&gt;// If the token is being refreshed, wait for the refresh to complete before sending a request.&lt;/span&gt;
     &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;tokenRefreshing&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;meta&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;authType&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;refreshToken&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
       &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Refreshing token, waiting for request&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
       &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
         &lt;span class="nx"&gt;waitingList&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
       &lt;span class="p"&gt;});&lt;/span&gt;
     &lt;span class="p"&gt;}&lt;/span&gt;
     &lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Authorization&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;token&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
   &lt;span class="p"&gt;},&lt;/span&gt;
   &lt;span class="na"&gt;responded&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;method&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
     &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;status&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="mi"&gt;401&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="c1"&gt;// token expires&lt;/span&gt;
       &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;method&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Token expires, get token again&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
       &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
           &lt;span class="c1"&gt;// This prevents requests to refresh the token multiple times, and intercepts and waits for requests sent before the token refresh is completed.&lt;/span&gt;
           &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;tokenRefreshing&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
             &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Refreshing token, waiting for request&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
             &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
               &lt;span class="nx"&gt;waitingList&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
             &lt;span class="p"&gt;});&lt;/span&gt;
           &lt;span class="p"&gt;})&lt;/span&gt;
         &lt;span class="nx"&gt;tokenRefreshing&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
         &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;token&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;newToken&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;refreshToken&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;newRefreshToken&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;refreshToken&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;refreshToken&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
         &lt;span class="nx"&gt;token&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;newToken&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
         &lt;span class="nx"&gt;refreshToken&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;newRefreshToken&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

         &lt;span class="nx"&gt;tokenRefreshing&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
         &lt;span class="nx"&gt;waitingList&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
         &lt;span class="nx"&gt;waitingList&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[];&lt;/span&gt;
         &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;New token has been obtained and saved&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;token&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;`Revisit &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;method&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

         &lt;span class="c1"&gt;// This is because the original interface is re-requested, and superposition with the previous request will result in repeated calls to transformData, so transformData needs to be left empty to remove one call.&lt;/span&gt;
         &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;methodTransformData&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;method&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;transformData&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
         &lt;span class="nx"&gt;method&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;transformData&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;undefined&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
         &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;dataResent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;method&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
         &lt;span class="nx"&gt;method&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;transformData&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;methodTransformData&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
         &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;dataResent&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
       &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
         &lt;span class="c1"&gt;// If the refresh token fails, you can handle operations such as jumping to the login interface.&lt;/span&gt;
         &lt;span class="c1"&gt;// ...&lt;/span&gt;
       &lt;span class="p"&gt;}&lt;/span&gt;
     &lt;span class="p"&gt;}&lt;/span&gt;
     &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
   &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So far, Alova's two ideas for refreshing tokens have been implemented, and there is no sense of token refresh at the request initiation point.&lt;/p&gt;

&lt;p&gt;If you want to learn more about the usage of alovajs, welcome to &lt;a href="https://alova.js.org/"&gt;alova official website&lt;/a&gt; to learn. If you also like alovajs, please contribute a star in &lt;a href="https://github.com/alovajs/alova"&gt;Github repository&lt;/a&gt;, which is very important to us.&lt;/p&gt;

&lt;p&gt;If you think the article is helpful to you, please don't be stingy with your likes and comments. Tell me what you think of alovajs, or ask some questions. I will try my best to answer them. Your support is the biggest motivation for my creation! Hahahahahaha~&lt;/p&gt;

&lt;h3&gt;
  
  
  Welcome to join our community
&lt;/h3&gt;

&lt;p&gt;If you have any questions, you can join the following group chat for consultation, or you can publish Discussions in &lt;a href="https://github.com/alovajs/alova/discussions"&gt;github repository&lt;/a&gt;. If you encounter problems, please also post in &lt;a href="https://github.com/alovajs/alova/issues"&gt;github issues &lt;/a&gt; and we will solve it as soon as possible.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://discord.gg/S47QGJgkVb"&gt;Join the Discord community to participate in communication&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You are also welcome to contribute, please go to &lt;a href="https://alova.js.org/contributing/overview"&gt;Contribution Guide&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>react</category>
      <category>svelte</category>
      <category>vue</category>
      <category>alova</category>
    </item>
    <item>
      <title>An amazing request tool which perfectly compatible with React, quick tutorial is HERE</title>
      <dc:creator>Scott Hu</dc:creator>
      <pubDate>Fri, 01 Dec 2023 10:07:55 +0000</pubDate>
      <link>https://dev.to/coderhu/an-amazing-request-tool-which-perfectly-compatible-with-react-quick-tutorial-is-here-827</link>
      <guid>https://dev.to/coderhu/an-amazing-request-tool-which-perfectly-compatible-with-react-quick-tutorial-is-here-827</guid>
      <description>&lt;p&gt;alova is a lightweight request strategy library designed to simplify the management and use of interfaces. By simply configuring parameters, you can implement complex requests such as sharing requests, paging requests, form submissions, breakpoint resumption, etc., without writing a lot of code, improving development efficiency, application performance, and reducing server pressure.&lt;/p&gt;

&lt;p&gt;After using alovajs, you only need to select the corresponding useHook to make a request. alova also supports the &lt;code&gt;vue/react/svelte&lt;/code&gt; framework. If you also like alovajs, please contribute a star in &lt;a href="https://github.com/alovajs/alova" rel="noopener noreferrer"&gt;Github repository&lt;/a&gt;, which is very important to us.&lt;/p&gt;

&lt;p&gt;This article serves as a basic introduction to react+alova. You can learn the following:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;How alova handles frequent requests and fuzzy searches gracefully&lt;/li&gt;
&lt;li&gt;How alova helps manage server status under react projects&lt;/li&gt;
&lt;li&gt;Smooth use of alova&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Welcome to join the communication community
&lt;/h2&gt;

&lt;p&gt;If you have any usage questions, you can join the following group chat for consultation, or you can publish Discussions in &lt;a href="https://github.com/alovajs/alova/discussions" rel="noopener noreferrer"&gt;github repository&lt;/a&gt;. If you encounter problems, please also post in &lt;a href="https://github.com/alovajs/alova/issues" rel="noopener noreferrer"&gt;github's issues&lt;/a&gt;, we will solve it as soon as possible.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://discord.gg/S47QGJgkVb" rel="noopener noreferrer"&gt;Join the Discord community to participate in communication&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You are also welcome to contribute, please go to &lt;a href="https://alova.js.org/contributing/overview" rel="noopener noreferrer"&gt;Contribution Guide&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Install alova
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install &lt;/span&gt;alova &lt;span class="nt"&gt;--save-dev&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Initialize an alova instance
&lt;/h2&gt;

&lt;p&gt;In the following introductory guide, we will use to-dos as an example to explain the needs of obtaining to-do lists for different dates, viewing todo details, and creating, editing, and deleting items!&lt;/p&gt;

&lt;p&gt;An &lt;code&gt;alova&lt;/code&gt; instance is the starting point from which all requests start. It is written similarly to &lt;code&gt;axios&lt;/code&gt;. The following is the simplest way to create an &lt;code&gt;alova&lt;/code&gt; instance.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;createAlova&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;alova&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;GlobalFetch&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;alova/GlobalFetch&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;ReactHook&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;alova/react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;alovaInstance&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;createAlova&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
   &lt;span class="c1"&gt;// Suppose we need to interact with the server of this domain name&lt;/span&gt;
   &lt;span class="na"&gt;baseURL&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://api.todo.com&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;

   &lt;span class="c1"&gt;// ReactHook is used to create ref status, including request status loading, response data data, request error object error, etc.&lt;/span&gt;
   &lt;span class="na"&gt;statesHook&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ReactHook&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;

   &lt;span class="c1"&gt;//Request adapter, here we use fetch request adapter&lt;/span&gt;
   &lt;span class="na"&gt;requestAdapter&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;GlobalFetch&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;

   &lt;span class="c1"&gt;//Set a global request interceptor, similar to axios&lt;/span&gt;
   &lt;span class="nf"&gt;beforeRequest&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
     &lt;span class="c1"&gt;// Suppose we need to add token to the request header&lt;/span&gt;
     &lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;token&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;token&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
   &lt;span class="p"&gt;},&lt;/span&gt;

   &lt;span class="c1"&gt;//Response interceptor, also similar to axios&lt;/span&gt;
   &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nf"&gt;responded&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
     &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;json&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
     &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;code&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
       &lt;span class="c1"&gt;// When an error is thrown here, it will enter the request failure interceptor.&lt;/span&gt;
       &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
     &lt;span class="p"&gt;}&lt;/span&gt;
     &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
   &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  todo list - directly use the state managed by &lt;code&gt;alova&lt;/code&gt; for interface rendering
&lt;/h2&gt;

&lt;p&gt;Our interface in this demo looks like this.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fp9-juejin.byteimg.com%2Ftos-cn-i-k3u1fbpfcp%2F7b00976f92a64d0396e83c09d813ea95~tplv-k3u1fbpfcp-watermark.image%23%3Fw%3D279%26h%3D408%26s%3D20261%2520%26e%3Dpng%26b%3Dfbf9ff" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fp9-juejin.byteimg.com%2Ftos-cn-i-k3u1fbpfcp%2F7b00976f92a64d0396e83c09d813ea95~tplv-k3u1fbpfcp-watermark.image%23%3Fw%3D279%26h%3D408%26s%3D20261%2520%26e%3Dpng%26b%3Dfbf9ff" alt="image.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We use &lt;code&gt;useRequest&lt;/code&gt; to send the request, which is the most commonly used method when the page obtains initialization data.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;todoListGetter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;alovaInstance&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/todo/list&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;TodoList&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
     &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
     &lt;span class="c1"&gt;//Loading is the loading status value. When loading, its value is true, and it is automatically updated to false after the end.&lt;/span&gt;
     &lt;span class="c1"&gt;// It is a Ref type value, you can access it through loading.value, or bind it directly to the interface&lt;/span&gt;
     &lt;span class="nx"&gt;loading&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;

     &lt;span class="c1"&gt;// response data&lt;/span&gt;
     &lt;span class="na"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;todoList&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;

     &lt;span class="c1"&gt;//Request error object, it has a value when requesting an error, otherwise it is undefined&lt;/span&gt;
     &lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;

     &lt;span class="c1"&gt;//Successful callback binding&lt;/span&gt;
     &lt;span class="nx"&gt;onSuccess&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;

     &lt;span class="c1"&gt;// Failure callback binding&lt;/span&gt;
     &lt;span class="nx"&gt;onError&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;

     &lt;span class="c1"&gt;//Complete callback binding&lt;/span&gt;
     &lt;span class="nx"&gt;onComplete&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;

     &lt;span class="c1"&gt;// Directly pass in the Method object to send the request&lt;/span&gt;
   &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useRequest&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;todoListGetter&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
     &lt;span class="c1"&gt;//Initial data data&lt;/span&gt;
     &lt;span class="na"&gt;initialData&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[],&lt;/span&gt;
   &lt;span class="p"&gt;});&lt;/span&gt;

   &lt;span class="c1"&gt;// ###### Callback settings&lt;/span&gt;
   &lt;span class="nf"&gt;onSuccess&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;todoListRaw&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
     &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;The request was successful, the response data is:&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;todoListRaw&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
   &lt;span class="p"&gt;});&lt;/span&gt;
   &lt;span class="nf"&gt;onError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
     &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;The request failed, the error message is:&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
   &lt;span class="p"&gt;});&lt;/span&gt;
   &lt;span class="nf"&gt;onComplete&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
     &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;The request is completed, it will be called regardless of success or failure&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
   &lt;span class="p"&gt;});&lt;/span&gt;

   &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;loading&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
     &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Loading...&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;;&lt;/span&gt;
   &lt;span class="p"&gt;}&lt;/span&gt;
   &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
     &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"error"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt; &lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;;&lt;/span&gt;
   &lt;span class="p"&gt;}&lt;/span&gt;
   &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;todoList&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;todo&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
     &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
       &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"todo"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
         &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"todo-title"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;todo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
         &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"todo-time"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
             &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;span&lt;/span&gt; &lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"time"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;todo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;startTime&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;span&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
             to
             &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;span&lt;/span&gt; &lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"time"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;todo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;endTime&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;span&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
         &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
       &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
     &lt;span class="p"&gt;);&lt;/span&gt;
   &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Todo list page - changed to fuzzy search for todo items
&lt;/h3&gt;

&lt;p&gt;The fuzzy search function is to continuously issue requests during the process of entering keywords. At this time, we replace the above useRequest with useWatcher to automatically re-obtain data when the keyword changes.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;In order to improve the user experience and reduce the pressure on the server, we have also implemented search anti-shake.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The implementation code is as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;TodoList&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="c1"&gt;// ...omit duplicate code&lt;/span&gt;

   &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;searchTodo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;keyword&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;alovaInstance&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`/todo/list?keyword=&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;keyword&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

   &lt;span class="c1"&gt;// Replace useRequest with useWatcher&lt;/span&gt;
   &lt;span class="c1"&gt;// Monitor keyword changes through useWatcher, and automatically reissue the request after the change&lt;/span&gt;
   &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;keyword&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setKeyword&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
   &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
     &lt;span class="nx"&gt;loading&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
     &lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
     &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
   &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useWatcher&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;searchTodo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;keyword&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;keyword&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
     &lt;span class="na"&gt;debounce&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;500&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// Set 500 milliseconds request-level anti-shake, no need to implement anti-shake function yourself&lt;/span&gt;
   &lt;span class="p"&gt;});&lt;/span&gt;

   &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="c1"&gt;// ...view code is the same as above&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this way, the fuzzy search function with anti-shake is realized.&lt;/p&gt;

&lt;h2&gt;
  
  
  todo editing page - cache frequently requested data in memory
&lt;/h2&gt;

&lt;p&gt;The edit page looks like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fp1-juejin.byteimg.com%2Ftos-cn-i-k3u1fbpfcp%2Fc400d3a9d14e475aa3cc0d057d217099~tplv-k3u1fbpfcp-watermark.image%23%3Fw%3D302%26h%3D519%26s%3D23320%2520%26e%3Dpng%26b%3Dffffff" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fp1-juejin.byteimg.com%2Ftos-cn-i-k3u1fbpfcp%2Fc400d3a9d14e475aa3cc0d057d217099~tplv-k3u1fbpfcp-watermark.image%23%3Fw%3D302%26h%3D519%26s%3D23320%2520%26e%3Dpng%26b%3Dffffff" alt="image.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Get the edit page data and echo it
&lt;/h3&gt;

&lt;p&gt;Our scenario needs to be considered here. The user clicks on a todo item multiple times within a few seconds to view it. It is a bit wasteful to request the server every time he enters. At this time, we can do a layer of front-end caching to increase the display speed and reduce the pressure on the server. .&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;todoDetail&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;alovaInstance&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`/todo/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
     &lt;span class="c1"&gt;//Set a local memory cache for 5 minutes, which will become invalid upon refreshing.&lt;/span&gt;
     &lt;span class="na"&gt;localeCache&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;60&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;TodoDetail&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
     &lt;span class="nx"&gt;loading&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;

     &lt;span class="c1"&gt;// response data&lt;/span&gt;
     &lt;span class="na"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;todoDetail&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
     &lt;span class="nx"&gt;update&lt;/span&gt;
   &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useRequest&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;todoDetail&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;

   &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;handleAddTodo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
     &lt;span class="c1"&gt;// Continue reading below&lt;/span&gt;
   &lt;span class="p"&gt;}&lt;/span&gt;

   &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;loading&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
     &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Loading...&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;;&lt;/span&gt;
   &lt;span class="p"&gt;}&lt;/span&gt;
   &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
     &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
       &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;input&lt;/span&gt; &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;todoDetail&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="na"&gt;onInput&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;update&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
         &lt;span class="na"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;todoDetail&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
           &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
         &lt;span class="p"&gt;}&lt;/span&gt;
       &lt;span class="p"&gt;})&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
       &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;input&lt;/span&gt; &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;todoDetail&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;date&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="na"&gt;onInput&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;update&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
         &lt;span class="na"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
         &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;todoDetail&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
           &lt;span class="na"&gt;date&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
         &lt;span class="p"&gt;}&lt;/span&gt;
       &lt;span class="p"&gt;})&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
       &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;input&lt;/span&gt; &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;todoDetail&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;startTime&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="na"&gt;onInput&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;update&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
         &lt;span class="na"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
         &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;todoDetail&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
           &lt;span class="na"&gt;startTime&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
         &lt;span class="p"&gt;}&lt;/span&gt;
       &lt;span class="p"&gt;})&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
       &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;input&lt;/span&gt; &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;todoDetail&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;endTime&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="na"&gt;onInput&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;update&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
         &lt;span class="na"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
         &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;todoDetail&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
           &lt;span class="na"&gt;endTime&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
         &lt;span class="p"&gt;}&lt;/span&gt;
       &lt;span class="p"&gt;})&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
       &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="cm"&gt;/* ... */&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
       &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt; &lt;span class="na"&gt;onClick&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;handleAddTodo&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Submit data&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
     &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
   &lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Data submission code - manually update todo list data
&lt;/h3&gt;

&lt;p&gt;Next, let's take a look at the operation of submitting data. We hope that it will directly update the data of the todo list across components after the submission is successful, instead of requesting data again to refresh the interface.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;TodoDetail&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="c1"&gt;// ...&lt;/span&gt;
   &lt;span class="c1"&gt;// First create a new request to submit data, and set immediate to false so that the request will not be sent during initialization.&lt;/span&gt;
   &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;createTodoPoster&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;newTodo&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;alova&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/todo&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;newTodo&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
   &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
     &lt;span class="na"&gt;loading&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;submitting&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
     &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
     &lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;

     &lt;span class="c1"&gt;// Manual sender request function, send the request after calling&lt;/span&gt;
     &lt;span class="na"&gt;send&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;submitTodo&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
   &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useRequest&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;createTodoPoster&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;todoDetail&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
     &lt;span class="c1"&gt;// When immediate is false, no request will be issued during initialization&lt;/span&gt;
     &lt;span class="na"&gt;immediate&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;
   &lt;span class="p"&gt;});&lt;/span&gt;

   &lt;span class="c1"&gt;// Trigger submission request&lt;/span&gt;
   &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;handleAddTodo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
     &lt;span class="nf"&gt;submitTodo&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
       &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
         &lt;span class="c1"&gt;//Update the list data, get the todo list status, and return the updated data&lt;/span&gt;
         &lt;span class="nf"&gt;updateState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;todoDetail&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="nx"&gt;todoListData&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
             &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;index&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;todoListData&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;findIndex&lt;/span&gt;&lt;span class="p"&gt;(({&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
             &lt;span class="nx"&gt;todoListData&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;index&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;todoDetail&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
             &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;todoListData&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
         &lt;span class="p"&gt;});&lt;/span&gt;
       &lt;span class="p"&gt;})&lt;/span&gt;
       &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
         &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Failed to add todo item, error message is:&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
       &lt;span class="p"&gt;});&lt;/span&gt;
   &lt;span class="p"&gt;};&lt;/span&gt;

   &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
     &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
       &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="cm"&gt;/*... */&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
       &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt; &lt;span class="na"&gt;loading&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;submiting&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="na"&gt;onClick&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;handleAddTodo&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Submit data&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
     &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
   &lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  End
&lt;/h1&gt;

&lt;p&gt;Now, you can also use alova in the options writing method of vue2, &lt;a href="https://alova.js.org/tutorial/framework/vue-options" rel="noopener noreferrer"&gt;click to view details&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://alova.js.org/category/examples" rel="noopener noreferrer"&gt;There are many runnable examples here&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you think the article is helpful to you, please don't be stingy with your likes and comments. Tell me what you think of alovajs, or ask some questions. I will try my best to answer them. Your support is the biggest motivation for my creation! Hahahahahaha~&lt;/p&gt;

&lt;p&gt;If you want to learn more about the usage of alovajs, welcome to &lt;a href="https://alova.js.org/" rel="noopener noreferrer"&gt;alova official website&lt;/a&gt; to learn. If you also like alovajs, please contribute a star in &lt;a href="https://github.com/alovajs/alova" rel="noopener noreferrer"&gt;Github repository&lt;/a&gt;, which is very important to us.&lt;/p&gt;

&lt;h3&gt;
  
  
  Welcome to join the communication community
&lt;/h3&gt;

&lt;p&gt;If you have any questions, you can join the following group chat for consultation, or you can publish Discussions in &lt;a href="https://github.com/alovajs/alova/discussions" rel="noopener noreferrer"&gt;github repository&lt;/a&gt;. If you encounter problems, please also post in &lt;a href="https://github.com/alovajs/alova/issues" rel="noopener noreferrer"&gt;github issues &lt;/a&gt; and we will solve it as soon as possible.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://discord.gg/S47QGJgkVb" rel="noopener noreferrer"&gt;Join the Discord community to participate in communication&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;At the same time, you are welcome to contribute, please go to &lt;a href="https://alova.js.org/contributing/overview" rel="noopener noreferrer"&gt;Contribution Area&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>react</category>
      <category>alova</category>
      <category>axios</category>
    </item>
    <item>
      <title>How to customize alova's request adapter</title>
      <dc:creator>Scott Hu</dc:creator>
      <pubDate>Thu, 23 Nov 2023 09:46:51 +0000</pubDate>
      <link>https://dev.to/coderhu/how-to-customize-alovas-request-adapter-4ddc</link>
      <guid>https://dev.to/coderhu/how-to-customize-alovas-request-adapter-4ddc</guid>
      <description>&lt;p&gt;alova is a lightweight request strategy library designed to simplify the management and use of interfaces. By simply configuring parameters, you can implement complex requests such as sharing requests, paging requests, form submissions, breakpoint resumption, etc., without writing a lot of code, improving development efficiency, application performance, and reducing server pressure.&lt;/p&gt;

&lt;p&gt;When using alova to send network requests, we often need to add some information to the request header, such as authentication tokens, public parameters, etc. alova provides two ways to configure request headers at global and individual request granularities. The method of adding request headers is very similar to axios.&lt;/p&gt;

&lt;h2&gt;
  
  
  Get to know the request adapter
&lt;/h2&gt;

&lt;p&gt;Remember how to create an Alova instance?&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;alovaInstance&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;createAlova&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
   &lt;span class="c1"&gt;// ...&lt;/span&gt;
   &lt;span class="na"&gt;requestAdapter&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;GlobalFetch&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Yes, &lt;code&gt;requestAdapter&lt;/code&gt; is a request adapter. Internal request sending and receiving will rely on the request adapter. &lt;code&gt;GlobalFetch&lt;/code&gt; manages requests through the fetch api. In most cases we can use it, but when&lt;code&gt;When alova&lt;/code&gt; is running in an environment where the fetch api is not available (such as app, applet), you need to replace a request adapter that supports the current environment.&lt;/p&gt;

&lt;h2&gt;
  
  
  Write an own request adapter
&lt;/h2&gt;

&lt;p&gt;So how to customize a request adapter? Very simple, it is actually a function. This function will be called every time a request is made, and an object will be returned. This object contains items such as &lt;code&gt;url&lt;/code&gt;, &lt;code&gt;method&lt;/code&gt;, &lt;code&gt;data&lt;/code&gt;, &lt;code&gt;headers&lt;/code&gt;, &lt;code&gt;timeout&lt;/code&gt;, etc. Request related data collections. Although there are many fields, we only need to access the data we need.&lt;/p&gt;

&lt;h3&gt;
  
  
  Request adapter structure
&lt;/h3&gt;

&lt;p&gt;The request adapter will receive the request-related parameters and the method instance currently being requested, and return a collection of response-related functions.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;CustomRequestAdapter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;requestElements&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;methodInstance&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="c1"&gt;// send request...&lt;/span&gt;
   &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
     &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nf"&gt;response&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
       &lt;span class="c1"&gt;// ...return response data&lt;/span&gt;
     &lt;span class="p"&gt;},&lt;/span&gt;
     &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nf"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
       &lt;span class="c1"&gt;// Asynchronous function that returns response headers&lt;/span&gt;
     &lt;span class="p"&gt;},&lt;/span&gt;
     &lt;span class="nf"&gt;abort&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
       &lt;span class="c1"&gt;//Interrupt request, this function will be triggered when abort is called externally&lt;/span&gt;
     &lt;span class="p"&gt;},&lt;/span&gt;
     &lt;span class="nf"&gt;onDownload&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;updateDownloadProgress&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
       &lt;span class="c1"&gt;//Download progress information, updateDownloadProgress is continuously called internally to update the download progress.&lt;/span&gt;
     &lt;span class="p"&gt;},&lt;/span&gt;
     &lt;span class="nf"&gt;onUpload&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;updateUploadProgress&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
       &lt;span class="c1"&gt;//Upload progress information, updateUploadProgress is continuously called internally to update the upload progress.&lt;/span&gt;
     &lt;span class="p"&gt;}&lt;/span&gt;
   &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Request parameter details
&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;requestElements&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Relevant elements of the send request, including the following data.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;RequestElements&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="c1"&gt;//Request url, get parameters are included in it&lt;/span&gt;
   &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

   &lt;span class="c1"&gt;// Request type, such as GET, POST, PUT, etc.&lt;/span&gt;
   &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="kd"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;MethodType&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

   &lt;span class="c1"&gt;//Request header information, object&lt;/span&gt;
   &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="nx"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Arg&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

   &lt;span class="c1"&gt;//Request body information&lt;/span&gt;
   &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="nx"&gt;RequestBody&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;methodInstance&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The method instance of the current request&lt;/p&gt;

&lt;h4&gt;
  
  
  Return parameter details
&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;response (required)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;An asynchronous function that returns the response value, which will be passed to the global response interceptor (responded);&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;headers (required)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;An asynchronous function, the response header object returned by the function will be passed to the transformData conversion hook function of the Method instance;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;abort (required)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A common function, which is used for interrupt requests. When the &lt;code&gt;abort&lt;/code&gt; function is called in the Manual Interrupt Request chapter, the function that actually triggers the interrupt request is this interrupt function;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;onDownload(optional)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A normal function that receives a callback function that updates the download progress. Customize the frequency of progress updates within this function. In this example, it simulates an update every 100 milliseconds. The &lt;code&gt;updateDownloadProgress&lt;/code&gt; callback function receives two parameters, the first parameter is the total size, and the second parameter is the downloaded size;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;onUpload(optional)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A normal function that receives a callback function that updates the upload progress. Customize the frequency of progress updates within this function. In this example, it simulates an update every 100 milliseconds. The &lt;code&gt;updateUploadProgress&lt;/code&gt; callback function receives two parameters, the first parameter is the total size, and the second parameter is the uploaded size;&lt;/p&gt;

&lt;h2&gt;
  
  
  (Case) XMLHttpRequest request adapter
&lt;/h2&gt;

&lt;p&gt;The following is an example of an adapter that sends requests through XMLHttpRequest. It is mainly used to demonstrate how to write the adapter. The code is incomplete and cannot be run.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;XMLHttpRequestAdapter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;requestElements&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;methodInstance&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="c1"&gt;// Deconstruct the data needed&lt;/span&gt;
   &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;type&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;headers&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

   &lt;span class="c1"&gt;// send request&lt;/span&gt;
   &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;xhr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;XMLHttpRequest&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
   &lt;span class="nx"&gt;xhr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;type&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
   &lt;span class="k"&gt;for &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;key&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="nx"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
     &lt;span class="nx"&gt;xhr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setRequestHeader&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
   &lt;span class="p"&gt;}&lt;/span&gt;
   &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;responsePromise&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;reject&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
     &lt;span class="nx"&gt;xhr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;load&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;event&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
       &lt;span class="c1"&gt;// Process response data&lt;/span&gt;
       &lt;span class="nf"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="cm"&gt;/* ... */&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
     &lt;span class="p"&gt;});&lt;/span&gt;
     &lt;span class="nx"&gt;xhr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;error&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;event&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
       &lt;span class="c1"&gt;// Handle request errors&lt;/span&gt;
       &lt;span class="nf"&gt;reject&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="cm"&gt;/* ... */&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
     &lt;span class="p"&gt;});&lt;/span&gt;
   &lt;span class="p"&gt;});&lt;/span&gt;

   &lt;span class="nx"&gt;xhr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;

   &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
     &lt;span class="c1"&gt;// Asynchronous function that returns response data&lt;/span&gt;
     &lt;span class="na"&gt;response&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;responsePromise&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;

     &lt;span class="c1"&gt;// Asynchronous function that returns response headers&lt;/span&gt;
     &lt;span class="na"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;responsePromise&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;xhr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getAllResponseHeaders&lt;/span&gt;&lt;span class="p"&gt;()),&lt;/span&gt;
     &lt;span class="na"&gt;abort&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
       &lt;span class="nx"&gt;xhr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;abort&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
     &lt;span class="p"&gt;},&lt;/span&gt;

     &lt;span class="c1"&gt;//Download progress information, updateDownloadProgress is continuously called internally to update the download progress.&lt;/span&gt;
     &lt;span class="na"&gt;onDownload&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;updateDownloadProgress&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
       &lt;span class="nx"&gt;xhr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;progress&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;event&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
         &lt;span class="c1"&gt;//Data receiving progress&lt;/span&gt;
         &lt;span class="nf"&gt;updateDownloadProgress&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;total&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;loaded&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
       &lt;span class="p"&gt;});&lt;/span&gt;
     &lt;span class="p"&gt;},&lt;/span&gt;

     &lt;span class="c1"&gt;//Upload progress information, updateUploadProgress is continuously called internally to update the upload progress.&lt;/span&gt;
     &lt;span class="na"&gt;onUpload&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;updateUploadProgress&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
       &lt;span class="nx"&gt;xhr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;upload&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;onprogress&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;event&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
         &lt;span class="nf"&gt;updateUploadProgress&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;total&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;loaded&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
       &lt;span class="p"&gt;};&lt;/span&gt;
     &lt;span class="p"&gt;}&lt;/span&gt;
   &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Complete XMLHttpRequest request adapter code &lt;a href="https://github.com/alovajs/adapter-xhr/blob/main/src/requestAdapter.ts"&gt;click here to view the source code&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  End
&lt;/h2&gt;

&lt;p&gt;The above is how to write alova's custom request adapter, which can flexibly handle different request header setting requirements.&lt;/p&gt;

&lt;p&gt;If you have any usage questions, you can join the following group chat for consultation, or you can publish Discussions in &lt;a href="https://github.com/alovajs/alova/discussions"&gt;github repository&lt;/a&gt;. If you encounter problems, please also post in &lt;a href="https://github.com/alovajs/alova/issues"&gt;github's issues&lt;/a&gt;, we will solve it as soon as possible.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://discord.gg/S47QGJgkVb"&gt;Join the Discord community to participate in communication&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You are also welcome to contribute, please go to &lt;a href="https://alova.js.org/contributing/overview"&gt;Contribution Guide&lt;/a&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The following is a tutorial for some chapters. If you want to learn more about the usage of alovajs, please come to &lt;a href="https://alova.js.org/"&gt;alova official website&lt;/a&gt; to learn.&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>vue</category>
      <category>react</category>
      <category>alova</category>
      <category>axios</category>
    </item>
    <item>
      <title>Transform response of alovajs, a request strategy library</title>
      <dc:creator>Scott Hu</dc:creator>
      <pubDate>Wed, 22 Nov 2023 05:46:04 +0000</pubDate>
      <link>https://dev.to/coderhu/transform-response-of-alovajs-a-request-strategy-library-2fp6</link>
      <guid>https://dev.to/coderhu/transform-response-of-alovajs-a-request-strategy-library-2fp6</guid>
      <description>&lt;p&gt;Alova is a lightweight request strategy library designed to simplify interface management and usage. It consists of 2 parts:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Declarative implementation of complex requests:&lt;/strong&gt; You can implement complex requests such as request sharing, pagination, form submission, breakpoint resume, etc. by simply configuring parameters without writing a lot of code, improving development efficiency and application performance and reduce pressure on the server.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;API automatic management and maintenance:&lt;/strong&gt; You no longer need to define the request functions by yourself, and you no longer need to consult the API documentation. alova can help you generate a complete and detailed TypeScript type of the request function, so that the front-end project can be integrated with the server-side seamless. When the server-side API is updated, the front-end project will also be notified and the project will be blocked from publishing.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://alova.js.org/category/examples"&gt;There are many runnable examples here&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;With Alova, all you need to do is select the appropriate useHook for your requests, now it support &lt;code&gt;React&lt;/code&gt;, &lt;code&gt;Vue&lt;/code&gt;, and &lt;code&gt;Svelte&lt;/code&gt;. If you find alova helpful, please consider star on &lt;a href="https://github.com/alovajs/alova"&gt;GitHub repository&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Join Our Community
&lt;/h2&gt;

&lt;p&gt;If you have any questions or need assistance, you can join our communication or start a discussion on &lt;a href="https://github.com/alovajs/alova/discussions"&gt;GitHub repository&lt;/a&gt; for support. If you encounter any issues, please submit them on &lt;a href="https://github.com/alovajs/alova/issues"&gt;GitHub issues&lt;/a&gt;, and we'll address them as soon as possible.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://discord.gg/S47QGJgkVb"&gt;Join Discord&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We also welcome contributions. For more information, please visit &lt;a href="https://alova.js.org/contributing/overview"&gt;contribution guidelines&lt;/a&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;For tutorials and more on how to use Alova, feel free to explore the &lt;a href="https://alova.js.org/"&gt;alova documentation&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Transform response data
&lt;/h2&gt;

&lt;p&gt;When the response data structure cannot directly meet the front-end requirements, we can set the &lt;code&gt;transformData&lt;/code&gt; hook function for the method instance to convert the response data into the required structure, and the data will be used as the value of the &lt;code&gt;data&lt;/code&gt; state after conversion.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;todoListGetter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;alovaInstance&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/todo/list&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;params&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;page&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;

  &lt;span class="c1"&gt;// The function accepts raw data and response header objects, and asks to return the converted data, which will be assigned to the data state.&lt;/span&gt;
  &lt;span class="c1"&gt;// Note: rawData is generally the data filtered by the response interceptor. For the configuration of the response interceptor, please refer to the [Setting the Global Response Interceptor] chapter.&lt;/span&gt;
  &lt;span class="nf"&gt;transformData&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;rawData&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;rawData&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;list&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;item&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;statusText&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;done&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;completed&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;in progress&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
      &lt;span class="p"&gt;};&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Note: &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;When used in usehooks, throwing an error in &lt;code&gt;transformData&lt;/code&gt; will trigger &lt;code&gt;onError&lt;/code&gt;;&lt;/li&gt;
&lt;li&gt;When sent a request by method instance, a rejected promise instance will be returned;&lt;/li&gt;
&lt;/ol&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  special usage of transformData
&lt;/h3&gt;

&lt;p&gt;Since the transformData function has the following two properties:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;It will only be triggered when the network request responds, and will not be triggered when the response cache is hit;&lt;/li&gt;
&lt;li&gt;Support asynchronous functions;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;You can also use it as a hook function for network request response. For example, in the cache scenario where files are used as response data, you can cooperate with IndexedDB to cache file data, and at the same time cooperate with &lt;a href="https://alova.js.org/tutorial/next-step/controlled-cache"&gt;Controlled cache&lt;/a&gt; to hit the file cache in IndexedDB.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;fileGetter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;alovaInstance&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/file/file_name&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// Use IndexedDB to cache files&lt;/span&gt;
  &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nf"&gt;transformData&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;fileBlob&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;reject&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;tx&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;transaction&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;files&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;readwrite&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;putRequest&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;tx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;objectStore&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;files&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;put&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
        &lt;span class="na"&gt;file&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;fileBlob&lt;/span&gt;
      &lt;span class="p"&gt;});&lt;/span&gt;
      &lt;span class="nx"&gt;putRequest&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;onsuccess&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="nx"&gt;putRequest&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;onerror&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;reject&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;fileBlob&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  (End)Why Use Alova
&lt;/h2&gt;

&lt;p&gt;Alova is committed to addressing client-side network request challenges, but what sets it apart from other request libraries is its focus on business-scenario-driven request strategies. When used in conjunction with libraries like &lt;code&gt;axios/fetch api&lt;/code&gt;, Alova can meet 99% of your request needs while offering a range of advanced features.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;You may have pondered over whether to encapsulate &lt;code&gt;fetch&lt;/code&gt; and &lt;code&gt;axios&lt;/code&gt;, but now you no longer need to. With Alova, you can use a declarative approach to fulfill complex requests, including request sharing, pagination, form submissions, and resumable uploads, as well as automated cache management, request sharing, and cross-component state updates.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Alova is lightweight, occupying only 4kb+, which is just over 30% of Axios's size.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;It currently supports &lt;code&gt;vue/react/react-native/svelte&lt;/code&gt; and SSR frameworks like &lt;code&gt;next/nuxt/sveltekit&lt;/code&gt;, as well as cross-platform frameworks like &lt;code&gt;Uniapp/Taro&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Alova is loosely coupled, allowing you to use it in any JavaScript environment with any UI framework using different adapters. It offers a unified user experience and seamless code migration.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Alova also promotes a highly organized approach for aggregating API code, grouping request parameters, cache behavior, and response data transformations in the same code blocks, which is advantageous for managing numerous APIs.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://alova.js.org/tutorial/get-started/comparison"&gt;Compare Alova with other request libraries&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Multi-Framework Support
&lt;/h2&gt;

&lt;p&gt;Now, you can perfectly use Alova in &lt;a href="https://vuejs.org/guide/introduction.html#api-styles"&gt;vue options (vue2 and vue3) syntax&lt;/a&gt;. In the future, we plan to support the following frameworks:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Functional ones like &lt;code&gt;solid/preact/qwik&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Class-based ones like &lt;code&gt;angular/lit/stencil&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Options-based ones like &lt;code&gt;native Chinese mini-programs&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Alova also offers powerful request strategies:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Name&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;th&gt;Documentation&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Pagination request strategy&lt;/td&gt;
&lt;td&gt;Automatically manage paging data, data preloading, reduce unnecessary data refresh, improve fluency by 300%, and reduce coding difficulty by 50%&lt;/td&gt;
&lt;td&gt;&lt;a href="https://alova.js.org/tutorial/strategy/usePagination"&gt;usePagination&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Non-sense data interaction strategy&lt;/td&gt;
&lt;td&gt;A new interactive experience, submission and response, greatly reducing the impact of network fluctuations, allowing your application to still be available when the network is unstable or even disconnected&lt;/td&gt;
&lt;td&gt;&lt;a href="https://alova.js.org/tutorial/strategy/sensorless-data-interaction/overview"&gt;useSQRequest&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Form submission strategy&lt;/td&gt;
&lt;td&gt;A hook designed for form submission. Through this hook, you can easily implement form drafts and multi-page (multi-step) forms. In addition, it also provides common functions such as form reset&lt;/td&gt;
&lt;td&gt;&lt;a href="https://alova.js.org/tutorial/strategy/useForm"&gt;useForm&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;File upload strategy&lt;/td&gt;
&lt;td&gt;A simpler file upload strategy that supports automatic identification and conversion of base64, Blob, ArrayBuffer, and Canvas data&lt;/td&gt;
&lt;td&gt;&lt;a href="https://alova.js.org/tutorial/strategy/useUploader"&gt;useUploader&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Send verification code&lt;/td&gt;
&lt;td&gt;Verification code sending hook reduces the complexity of developing the verification code sending function.&lt;/td&gt;
&lt;td&gt;&lt;a href="https://alova.js.org/tutorial/strategy/useCaptcha"&gt;useCaptcha&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Automatically re-pull data&lt;/td&gt;
&lt;td&gt;Automatically re-pull data under certain conditions to ensure that the latest data is always displayed.&lt;/td&gt;
&lt;td&gt;&lt;a href="https://alova.js.org/tutorial/strategy/useAutoRequest"&gt;useAutoRequest&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Trigger requests across components&lt;/td&gt;
&lt;td&gt;An alova middleware that eliminates component-level restrictions and quickly triggers the operation function of any request in any component&lt;/td&gt;
&lt;td&gt;&lt;a href="https://alova.js.org/tutorial/strategy/actionDelegationMiddleware"&gt;actionDelegationMiddleware&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;UseRequest for serial requests&lt;/td&gt;
&lt;td&gt;A more concise and easy-to-use serial request use hook than &lt;a href="https://alova.js.org/tutorial/next-step/serial-request"&gt;alova's serial request method&lt;/a&gt;, providing a unified loading status, error, callback function&lt;/td&gt;
&lt;td&gt;&lt;a href="https://alova.js.org/tutorial/strategy/useSerialRequest"&gt;useSerialRequest&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;UseWatcher for serial requests&lt;/td&gt;
&lt;td&gt;A more concise and easy-to-use serial request use hook than &lt;a href="https://alova.js.org/tutorial/next-step/serial-request"&gt;alova's serial request method&lt;/a&gt;, providing a unified loading status, error, callback function.&lt;/td&gt;
&lt;td&gt;&lt;a href="https://alova.js.org/tutorial/strategy/useSerialWatcher"&gt;useSerialWatcher&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Request retry strategy&lt;/td&gt;
&lt;td&gt;Automatic retry on request failure, which plays an important role on important requests and polling requests&lt;/td&gt;
&lt;td&gt;&lt;a href="https://alova.js.org/tutorial/strategy/useRetriableRequest"&gt;useRetriableRequest&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;SSE requests&lt;/td&gt;
&lt;td&gt;Requests via Server-sent Events&lt;/td&gt;
&lt;td&gt;&lt;a href="https://alova.js.org/tutorial/strategy/useSSE"&gt;useSSE&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;For more in-depth learning about Alova, please visit the &lt;a href="https://alova.js.org/"&gt;Alova documentation&lt;/a&gt;. If you find Alova helpful, please star on &lt;a href="https://github.com/alovajs/alova"&gt;GitHub repository&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;If you find this article helpful, don't hesitate to like and comment. Share your thoughts on Alova or ask any questions you may have. Your support is our greatest motivation!&lt;/p&gt;

&lt;h3&gt;
  
  
  Join Our Community
&lt;/h3&gt;

&lt;p&gt;If you have any questions, you can join our community chat groups or start discussions on the &lt;a href="https://github.com/alovajs/alova/discussions"&gt;GitHub repository&lt;/a&gt;. If you encounter any issues, please submit them on &lt;a href="https://github.com/alovajs/alova/issues"&gt;GitHub's issues page&lt;/a&gt;, and we will address them promptly.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://discord.gg/S47QGJgkVb"&gt;Join our Discord community for discussions&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We also welcome contributions. For more information, please visit our &lt;a href="https://alova.js.org/contributing/overview"&gt;contribution guidelines&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>react</category>
      <category>vue</category>
      <category>svelte</category>
    </item>
    <item>
      <title>Alova is coming, are you still using axios?</title>
      <dc:creator>Scott Hu</dc:creator>
      <pubDate>Wed, 15 Nov 2023 03:49:27 +0000</pubDate>
      <link>https://dev.to/coderhu/damn-the-request-logic-finish-your-business-logic-and-get-off-work-34b5</link>
      <guid>https://dev.to/coderhu/damn-the-request-logic-finish-your-business-logic-and-get-off-work-34b5</guid>
      <description>&lt;p&gt;Hello, I am Scott.&lt;/p&gt;

&lt;p&gt;Today, I want to talk something that when we write project code, we should focus more on the implementation of business logic, and hand over the fixed code to the js library or engineering for automatic processing. What I want to say is that the request logic can actually continue simplified.&lt;/p&gt;

&lt;p&gt;You may say that using &lt;code&gt;axios&lt;/code&gt; or &lt;code&gt;fetch api&lt;/code&gt; is enough. There is no request logic. That may be because you are not aware of this problem. As a front-end developer, you must have encountered these problems:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Handle paging logic.&lt;/li&gt;
&lt;li&gt;Form processing logic.&lt;/li&gt;
&lt;li&gt;Process request debounce logic.&lt;/li&gt;
&lt;li&gt;Handle polling checks.&lt;/li&gt;
&lt;li&gt;Handle cache handling.&lt;/li&gt;
&lt;li&gt;Handle loading status.&lt;/li&gt;
&lt;li&gt;Handle error handling.&lt;/li&gt;
&lt;li&gt;Captcha sent.&lt;/li&gt;
&lt;li&gt;File Upload.
-...&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These problems, if you are using &lt;code&gt;axios&lt;/code&gt; or &lt;code&gt;fetch api&lt;/code&gt;, you need to write a lot of code to deal with these problems, but I want to say that they are actually more fixed template codes and can also be streamlined.&lt;/p&gt;

&lt;p&gt;Today you can use &lt;code&gt;alova&lt;/code&gt; to handle them. &lt;code&gt;alova&lt;/code&gt; provides a large number of request modules commonly used in daily business. You only need to simply configure a few lines of code, and &lt;code&gt;alova&lt;/code&gt; can automatically help you manage the request status, optimize the network experience, and eliminate those annoying paging logic. , polling check, cache processing, all of which you don’t have to worry about, allowing you to focus more on business logic.&lt;/p&gt;

&lt;h2&gt;
  
  
  alova’s learning cost is lower
&lt;/h2&gt;

&lt;p&gt;alova draws on the design of axios and ahooks-useRequest, making it easier for everyone to get started and with lower learning costs.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;a href="https://alova.js.org/"&gt;alova official website&lt;/a&gt; is here.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;If you also like alovajs, please contribute a star in &lt;a href="https://github.com/alovajs/alova"&gt;Github repository&lt;/a&gt;, which is very important to us.&lt;/p&gt;

&lt;p&gt;Let's take a look at how simple configuration can help you solve request problems in various complex scenarios.&lt;/p&gt;

&lt;h2&gt;
  
  
  Basic request
&lt;/h2&gt;

&lt;p&gt;Basic request, suitable for initialization information, comes with various statuses related to the request.&lt;/p&gt;

&lt;p&gt;Take vue3 as an example.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;template&amp;gt;&lt;/span&gt;
   &lt;span class="nt"&gt;&amp;lt;div&amp;gt;&lt;/span&gt;
     &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;v-if=&lt;/span&gt;&lt;span class="s"&gt;"loading"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;loading...&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
     &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;v-else-if=&lt;/span&gt;&lt;span class="s"&gt;"error"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;error: {{ error }}&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
     &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;v-else&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
       &lt;span class="nt"&gt;&amp;lt;div&amp;gt;&lt;/span&gt;
         &lt;span class="nt"&gt;&amp;lt;span&amp;gt;&lt;/span&gt;id: {{ data.title }}&lt;span class="nt"&gt;&amp;lt;/span&amp;gt;&lt;/span&gt;
         &lt;span class="nt"&gt;&amp;lt;span&amp;gt;&lt;/span&gt;title: {{ data.time }}&lt;span class="nt"&gt;&amp;lt;/span&amp;gt;&lt;/span&gt;
       &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
     &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
   &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/template&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;setup&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
   &lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useRequest&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;alova&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

   &lt;span class="c1"&gt;// Parameter style similar to axios&lt;/span&gt;
   &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;todoDetail&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;alova&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/todo&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
     &lt;span class="na"&gt;params&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
       &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
     &lt;span class="p"&gt;},&lt;/span&gt;
   &lt;span class="p"&gt;});&lt;/span&gt;

   &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
     &lt;span class="nx"&gt;loading&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
     &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
     &lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
     &lt;span class="nx"&gt;onSuccess&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
     &lt;span class="nx"&gt;onError&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
     &lt;span class="nx"&gt;onComplete&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
     &lt;span class="nx"&gt;send&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
     &lt;span class="nx"&gt;abort&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
     &lt;span class="nx"&gt;update&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
   &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useRequest&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;todoDetail&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
   &lt;span class="nx"&gt;onSuccess&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
     &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;success&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
   &lt;span class="p"&gt;});&lt;/span&gt;
   &lt;span class="nx"&gt;onError&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
     &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;error&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
   &lt;span class="p"&gt;});&lt;/span&gt;
   &lt;span class="nx"&gt;onComplete&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
     &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;complete&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
   &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;useRequest will automatically help you manage loading, data, error and other states, so you don’t need to control it yourself!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://alova.js.org/tutorial/learning/use-request"&gt;useRequest detailed documentation&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Status change request
&lt;/h2&gt;

&lt;p&gt;In interactions such as data filtering and search, you can use useWatcher to monitor state changes and send requests. The return value also contains the same state, event function, and operation function as useRequest.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;useWatcher&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;filterTodoList&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;keyword&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;keyword&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="na"&gt;debounce&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;500&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="c1"&gt;// Request-level anti-shake parameters&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It also has functions such as requesting anti-shake, ensuring request timing, filtering whether to send requests when the status changes, etc., which is super convenient!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://alova.js.org/tutorial/learning/use-watcher"&gt;useWatcher detailed documentation&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Preload data
&lt;/h2&gt;

&lt;p&gt;You can use useFetcher to preload data. There is no need to directly process the response, but the relevant status will be updated:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;fetching&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;fetch&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useFetcher&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="nx"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;todoDetail&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://alova.js.org/tutorial/learning/use-fetcher"&gt;useFetcher detailed documentation&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Pagination request
&lt;/h2&gt;

&lt;p&gt;In the paging scenario, many states such as page, pageSize, pageCount, total, etc. need to be maintained by yourself, and a lot of logic must be written to determine when a request should be sent!&lt;/p&gt;

&lt;p&gt;If you use the paging Hook provided by alovajs, you only need this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="c1"&gt;// loading status&lt;/span&gt;
   &lt;span class="nx"&gt;loading&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;

   &lt;span class="c1"&gt;// list data&lt;/span&gt;
   &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;

   &lt;span class="c1"&gt;// Is it the last page?&lt;/span&gt;
   &lt;span class="c1"&gt;// When pulling down to load, you can use this parameter to determine whether it still needs to be loaded.&lt;/span&gt;
   &lt;span class="nx"&gt;isLastPage&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;

   &lt;span class="c1"&gt;//Current page number, changing this page number will automatically trigger the request&lt;/span&gt;
   &lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;

   &lt;span class="c1"&gt;//Number of data items per page&lt;/span&gt;
   &lt;span class="nx"&gt;pageSize&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;

   &lt;span class="c1"&gt;//Number of pagination pages&lt;/span&gt;
   &lt;span class="nx"&gt;pageCount&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;

   &lt;span class="c1"&gt;//Total amount of data&lt;/span&gt;
   &lt;span class="nx"&gt;total&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;usePagination&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;pageSize&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;queryStudents&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;pageSize&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;

&lt;span class="c1"&gt;// Turn to the previous page, and the request will be automatically sent after the page value is changed.&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;handlePrevPage&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="c1"&gt;// Turn to the next page, the request will be automatically sent after the page value changes&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;handleNextPage&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="c1"&gt;//Change the number of pages per page. The request will be automatically sent after the pageSize value is changed.&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;handleSetPageSize&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="nx"&gt;pageSize&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Isn’t it much cleaner and saves a lot of repeated code?&lt;/p&gt;

&lt;p&gt;&lt;a href="https://alova.js.org/tutorial/strategy/usePagination"&gt;usePagination detailed documentation&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Form submission
&lt;/h2&gt;

&lt;p&gt;Form processing is also a headache, right? alova's useForm directly helps you with form submission, form drafts, automatic reset of form items, multi-page sharing of data, etc.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="nx"&gt;form&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
   &lt;span class="na"&gt;send&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;submitForm&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
   &lt;span class="nx"&gt;updateForm&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useForm&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;formData&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;submitData&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;formData&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="na"&gt;initialForm&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
     &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
     &lt;span class="na"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
     &lt;span class="na"&gt;time&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
   &lt;span class="p"&gt;},&lt;/span&gt;
   &lt;span class="na"&gt;resetAfterSubmiting&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://alova.js.org/tutorial/strategy/useForm"&gt;useForm detailed documentation&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Verification code implementation
&lt;/h2&gt;

&lt;p&gt;Stop making your own countdowns, this is it!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;loading&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;sending&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;send&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;sendCaptcha&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useCaptcha&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
   &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;sendCaptcha&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;mobile&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
   &lt;span class="p"&gt;{&lt;/span&gt;
     &lt;span class="na"&gt;initialCountdown&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;60&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
   &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://alova.js.org/tutorial/strategy/useCaptcha"&gt;useCaptcha detailed documentation&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  File upload strategy
&lt;/h2&gt;

&lt;p&gt;A simpler file upload strategy that supports automatic identification and conversion of base64, Blob, ArrayBuffer, and Canvas data. It can also upload multiple files at the same time and generate image previews.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="nx"&gt;fileList&lt;/span&gt;
   &lt;span class="nx"&gt;loading&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
   &lt;span class="nx"&gt;progress&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useUploader&lt;/span&gt;&lt;span class="p"&gt;(({&lt;/span&gt; &lt;span class="nx"&gt;file&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;uploadFile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;file&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="na"&gt;limit&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
   &lt;span class="na"&gt;accept&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;png&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;jpg&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;gif&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
   &lt;span class="na"&gt;imageTempLink&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://alova.js.org/tutorial/strategy/useUploader"&gt;useUploader detailed documentation&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Automatically re-pull data
&lt;/h2&gt;

&lt;p&gt;The latest data can be pulled when the browser tab is switched, the latest data can be pulled when the browser is focused, the latest data can be pulled when the network is reconnected, and the data can be automatically re-pulled by polling request. One or more of the above trigger conditions can be configured at the same time. , you can also configure the throttling time to prevent multiple requests from being triggered in a short period of time. For example, only one trigger is allowed within 1 second.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;useAutoRequest&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;todoDetail&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="na"&gt;enablePolling&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
   &lt;span class="na"&gt;enableVisibility&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
   &lt;span class="na"&gt;enableFocus&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
   &lt;span class="na"&gt;enableNetwork&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
   &lt;span class="na"&gt;throttle&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://alova.js.org/tutorial/strategy/useAutoRequest"&gt;useAutoRequest detailed documentation&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Cross-component request strategy
&lt;/h2&gt;

&lt;p&gt;Trigger request-related operations across components or modules, eliminate component-level restrictions, and quickly trigger any requested operation function in any component. For example, you can re-trigger the side menu bar after updating the menu data in a component. request to refresh the data. When the list data is manipulated, a list update is triggered.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Component A creates a proxy&lt;/span&gt;
&lt;span class="nx"&gt;useRequest&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;todoDetail&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="na"&gt;middleware&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;actionDelegationMiddleware&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;someAction&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="c1"&gt;// Trigger operation in component B&lt;/span&gt;
&lt;span class="nx"&gt;accessAction&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;someAction&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;actions&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="nx"&gt;actions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;send&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://alova.js.org/tutorial/strategy/actionDelegationMiddleware"&gt;actionDelegationMiddleware detailed documentation&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Request retry strategy
&lt;/h2&gt;

&lt;p&gt;Use it on important requests to improve the stability of the request. You can customize whether to retry, the retry delay, and manually stop retrying.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;onRetry&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;onFail&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;stop&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useRetriableRequest&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;pay&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="nx"&gt;retry&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
     &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="sr"&gt;/network timeout/i&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;test&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
   &lt;span class="p"&gt;},&lt;/span&gt;
   &lt;span class="na"&gt;backoff&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
     &lt;span class="na"&gt;delay&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
   &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://alova.js.org/tutorial/strategy/useRetriableRequest"&gt;useRetriableRequest detailed documentation&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  SSE
&lt;/h2&gt;

&lt;p&gt;Requests can be made directly through SSE, which can be automatically transformed through the function transformData of global responses and method instances.data and also provides full control over the EventSource object.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;readyState&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;eventSource&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;onMessage&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;onError&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;onOpen&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;on&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
   &lt;span class="nx"&gt;useSSE&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;chatGPT&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
     &lt;span class="na"&gt;withCredentials&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
     &lt;span class="na"&gt;interceptByGlobalResponded&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
   &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://alova.js.org/tutorial/strategy/useSSE"&gt;useSSE detailed documentation&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  end
&lt;/h1&gt;

&lt;p&gt;Now, you can also use alova in the options writing method of vue2, &lt;a href="https://alova.js.org/tutorial/framework/vue-options"&gt;click to view details&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://alova.js.org/category/examples"&gt;There are many runnable examples here&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you think the article is helpful to you, please don't be stingy with your likes and comments. Tell me what you think of alovajs, or ask some questions. I will try my best to answer them. Your support is the biggest motivation for my creation! Hahahahahaha~&lt;/p&gt;

&lt;p&gt;If you want to learn more about the usage of alovajs, welcome to &lt;a href="https://alova.js.org/"&gt;alova official website&lt;/a&gt; to learn. If you also like alovajs, please contribute a star in &lt;a href="https://github.com/alovajs/alova"&gt;Github repository&lt;/a&gt;, which is very important to us.&lt;/p&gt;

&lt;h3&gt;
  
  
  Welcome to join the communication community
&lt;/h3&gt;

&lt;p&gt;If you have any questions, you can join the following group chat for consultation, or you can publish Discussions in &lt;a href="https://github.com/alovajs/alova/discussions"&gt;github repository&lt;/a&gt;. If you encounter problems, please also post in &lt;a href="https://github.com/alovajs/alova/issues"&gt;github issues &lt;/a&gt; and we will solve it as soon as possible.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://discord.gg/S47QGJgkVb"&gt;Join the Discord community to participate in communication&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;At the same time, you are welcome to contribute, please go to &lt;a href="https://alova.js.org/contributing/overview"&gt;Contribution guidelines&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>vue</category>
      <category>react</category>
      <category>svelte</category>
      <category>alova</category>
    </item>
    <item>
      <title>Cache mode of alovajs, a request strategy library</title>
      <dc:creator>Scott Hu</dc:creator>
      <pubDate>Fri, 10 Nov 2023 09:33:28 +0000</pubDate>
      <link>https://dev.to/coderhu/cache-mode-of-alovajs-a-request-strategy-library-4jki</link>
      <guid>https://dev.to/coderhu/cache-mode-of-alovajs-a-request-strategy-library-4jki</guid>
      <description>&lt;p&gt;Alova is a lightweight request strategy library designed to simplify interface management and usage. It consists of 2 parts:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Declarative implementation of complex requests:&lt;/strong&gt; You can implement complex requests such as request sharing, pagination, form submission, breakpoint resume, etc. by simply configuring parameters without writing a lot of code, improving development efficiency and application performance and reduce pressure on the server.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;API automatic management and maintenance:&lt;/strong&gt; You no longer need to define the request functions by yourself, and you no longer need to consult the API documentation. alova can help you generate a complete and detailed TypeScript type of the request function, so that the front-end project can be integrated with the server-side seamless. When the server-side API is updated, the front-end project will also be notified and the project will be blocked from publishing.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://alova.js.org/category/examples"&gt;There are many runnable examples here&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;With Alova, all you need to do is select the appropriate useHook for your requests, now it support &lt;code&gt;React&lt;/code&gt;, &lt;code&gt;Vue&lt;/code&gt;, and &lt;code&gt;Svelte&lt;/code&gt;. If you find alova helpful, please consider star on &lt;a href="https://github.com/alovajs/alova"&gt;GitHub repository&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Join Our Community
&lt;/h2&gt;

&lt;p&gt;If you have any questions or need assistance, you can join our communication or start a discussion on &lt;a href="https://github.com/alovajs/alova/discussions"&gt;GitHub repository&lt;/a&gt; for support. If you encounter any issues, please submit them on &lt;a href="https://github.com/alovajs/alova/issues"&gt;GitHub issues&lt;/a&gt;, and we'll address them as soon as possible.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://discord.gg/S47QGJgkVb"&gt;Join Discord&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We also welcome contributions. For more information, please visit &lt;a href="https://alova.js.org/contributing/overview"&gt;contribution guidelines&lt;/a&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;For tutorials and more on how to use Alova, feel free to explore the &lt;a href="https://alova.js.org/"&gt;alova documentation&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Cache mode
&lt;/h2&gt;

&lt;p&gt;The cache mode can make better use of server-side data multiple times without sending a request to get data every time a request is made. &lt;code&gt;alova&lt;/code&gt; provides three cache modes to meet different cache scenarios, namely memory mode, cache replaceholder mode, and restore mode. The cache mode can be set at different granularities such as global or request level. When set globally, all Method instances created from the same alova instance will inherit the setting.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;note: Whether to use the cache mode and which cache mode to use depends on the scenario. The usage scenarios of different cache modes will be mentioned below when introducing different cache modes separately.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  memory mode (default)
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;memory mode example: &lt;a href="https://alova.js.org/tutorial/example/memory-cache"&gt;Click here to view&lt;/a&gt;。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The memory mode puts the cache in the memory, which means that the page cache is invalidated when it is refreshed, and is the most commonly used cache mode.&lt;/p&gt;

&lt;p&gt;Memory mode is generally used to solve the performance consumption caused by frequent requests for the same data in a short period of time (minutes or seconds). For example, when you are writing a todo details page, you may think that users will frequently click on the todo list Check the details, if the user does not repeatedly request the interface when repeatedly viewing a certain detail, and can return the data immediately, the colleague who improves the response speed also reduces the pressure on the server. At this point we can set the response data cache for a todo detail &lt;code&gt;Method&lt;/code&gt; instance.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;alovaInstance&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;GET&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/todo/list&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;//...&lt;/span&gt;
  &lt;span class="c1"&gt;// highlight-start&lt;/span&gt;
  &lt;span class="na"&gt;localCache&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Set cache mode to memory mode&lt;/span&gt;
    &lt;span class="na"&gt;mode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;memory&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;

    &lt;span class="c1"&gt;// unit is milliseconds&lt;/span&gt;
    &lt;span class="c1"&gt;// When set to `Infinity`, it means that the data will never expire, and when it is set to 0 or a negative number, it means no caching&lt;/span&gt;
    &lt;span class="na"&gt;expire&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;60&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="c1"&gt;// highlight-end&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Memory mode is the default mode, you can abbreviate like this&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;alovaInstance&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;GET&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/todo/list&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;//...&lt;/span&gt;
  &lt;span class="c1"&gt;// highlight-start&lt;/span&gt;
  &lt;span class="na"&gt;localCache&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;60&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;
  &lt;span class="c1"&gt;// highlight-end&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;GET requests will set the memory cache time of 300000ms (5 minutes) by default, and developers can also customize the settings.&lt;/p&gt;

&lt;p&gt;If you need to set the caching mode globally, see [Global setting cache mode] at the bottom of this section (#Global setting cache mode)&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  cache replaceholder mode
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;cache replaceholder mode example: &lt;a href="https://alova.js.org/tutorial/example/storage-placeholder"&gt;Click here to view&lt;/a&gt;。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This cache mode is used when you don't want to display the Loading icon every time the application is entered, but you want to use the old data instead, you can use the cache occupancy mode, which has a better experience than Loading.&lt;/p&gt;

&lt;p&gt;In the cache occupancy mode, &lt;code&gt;data&lt;/code&gt; will be immediately assigned the old data of the last cache. You can judge that if there is old data, use it to replace the Loading display. At the same time, it will send a request to obtain the latest data and update the cache, so as to achieve In order to quickly display the actual data, and obtain the latest data.&lt;/p&gt;

&lt;p&gt;Set on &lt;code&gt;Method&lt;/code&gt; instances:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;todoListGetter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;alovaInstance&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/todo/list&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;//...&lt;/span&gt;
  &lt;span class="c1"&gt;// highlight-start&lt;/span&gt;
  &lt;span class="na"&gt;localCache&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Set the cache mode to persistent placeholder mode&lt;/span&gt;
    &lt;span class="na"&gt;mode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;placeholder&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="c1"&gt;// cache time&lt;/span&gt;
    &lt;span class="na"&gt;expire&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;60&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="c1"&gt;// highlight-end&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;If you need to set the caching mode globally, see [Global setting cache mode] at the bottom of this section (#Global setting cache mode)&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  restore mode
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;restore mode example: &lt;a href="https://alova.js.org/tutorial/example/storage-restore"&gt;Click here to view&lt;/a&gt;。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In this mode, the server-side cached data will be persistent. If the expiration time is not reached, even if the page cache is refreshed, it will not be invalidated. It is generally used for some data that requires server-side management but is basically unchanged, such as the specific dates of annual holidays. It is different, but it will not change again. In this scenario, we only need to set the cache expiration time to the last moment of this year.&lt;/p&gt;

&lt;p&gt;Set on &lt;code&gt;Method&lt;/code&gt; instances:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;todoListGetter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;alovaInstance&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/todo/list&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;//...&lt;/span&gt;
  &lt;span class="c1"&gt;// highlight-start&lt;/span&gt;
  &lt;span class="na"&gt;localCache&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Set the cache mode to persistent mode&lt;/span&gt;
    &lt;span class="na"&gt;mode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;restore&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="c1"&gt;// cache time&lt;/span&gt;
    &lt;span class="na"&gt;expire&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;60&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="c1"&gt;// highlight-end&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Note: When request body is special data such as &lt;strong&gt;FormData&lt;/strong&gt;, &lt;strong&gt;Blob&lt;/strong&gt;, &lt;strong&gt;ArrayBuffer&lt;/strong&gt;, &lt;strong&gt;URLSearchParams&lt;/strong&gt;, &lt;strong&gt;ReadableStream&lt;/strong&gt;, it will be considered that you intend to communicate with server. In this case would not cache data.&lt;/p&gt;

&lt;p&gt;If you need to set the caching mode globally, see [Global setting cache mode] at the bottom of this section (#Global setting cache mode)&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  What should I do if the data changes in restore mode?
&lt;/h3&gt;

&lt;p&gt;When the &lt;code&gt;Method&lt;/code&gt; instance in restore mode is set, it may be due to the change of the interface data or the logic change of the front-end processing response data. At this time, it is necessary to let the user re-cache the changed data after publishing the application. At this time, you can use &lt;code&gt;tag&lt;/code&gt; The attribute sets the cache tag. Each piece of persistent data contains a &lt;code&gt;tag&lt;/code&gt; identifier. When the &lt;code&gt;tag&lt;/code&gt; changes, the original persistent data will become invalid, and new data will be obtained again, and the new &lt;code&gt;tag&lt;/code&gt; will be used for identification .&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;todoListGetter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;alovaInstance&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/todo/list&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;//...&lt;/span&gt;
  &lt;span class="na"&gt;localCache&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;mode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;restore&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;expire&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;60&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;

    &lt;span class="c1"&gt;// highlight-start&lt;/span&gt;
    &lt;span class="c1"&gt;// Add or modify the tag parameter, the cached data will be invalid&lt;/span&gt;
    &lt;span class="c1"&gt;// It is recommended to use version number management&lt;/span&gt;
    &lt;span class="na"&gt;tag&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;v1&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
    &lt;span class="c1"&gt;// highlight-end&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Cache key automatic maintenance
&lt;/h3&gt;

&lt;p&gt;The key of the response data cache is uniquely identified by the combination of the request method (method), request address (url), request header parameters (headers), url parameters (params), and request body parameters (requestBody) of the method instance. Any information or Different positions will be treated as different keys.&lt;/p&gt;

&lt;h2&gt;
  
  
  (End)Why Use Alova
&lt;/h2&gt;

&lt;p&gt;Alova is committed to addressing client-side network request challenges, but what sets it apart from other request libraries is its focus on business-scenario-driven request strategies. When used in conjunction with libraries like &lt;code&gt;axios/fetch api&lt;/code&gt;, Alova can meet 99% of your request needs while offering a range of advanced features.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;You may have pondered over whether to encapsulate &lt;code&gt;fetch&lt;/code&gt; and &lt;code&gt;axios&lt;/code&gt;, but now you no longer need to. With Alova, you can use a declarative approach to fulfill complex requests, including request sharing, pagination, form submissions, and resumable uploads, as well as automated cache management, request sharing, and cross-component state updates.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Alova is lightweight, occupying only 4kb+, which is just over 30% of Axios's size.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;It currently supports &lt;code&gt;vue/react/react-native/svelte&lt;/code&gt; and SSR frameworks like &lt;code&gt;next/nuxt/sveltekit&lt;/code&gt;, as well as cross-platform frameworks like &lt;code&gt;Uniapp/Taro&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Alova is loosely coupled, allowing you to use it in any JavaScript environment with any UI framework using different adapters. It offers a unified user experience and seamless code migration.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Alova also promotes a highly organized approach for aggregating API code, grouping request parameters, cache behavior, and response data transformations in the same code blocks, which is advantageous for managing numerous APIs.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://alova.js.org/tutorial/get-started/comparison"&gt;Compare Alova with other request libraries&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Multi-Framework Support
&lt;/h2&gt;

&lt;p&gt;Now, you can perfectly use Alova in &lt;a href="https://vuejs.org/guide/introduction.html#api-styles"&gt;vue options (vue2 and vue3) syntax&lt;/a&gt;. In the future, we plan to support the following frameworks:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Functional ones like &lt;code&gt;solid/preact/qwik&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Class-based ones like &lt;code&gt;angular/lit/stencil&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Options-based ones like &lt;code&gt;native Chinese mini-programs&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Alova also offers powerful request strategies:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Name&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;th&gt;Documentation&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Pagination request strategy&lt;/td&gt;
&lt;td&gt;Automatically manage paging data, data preloading, reduce unnecessary data refresh, improve fluency by 300%, and reduce coding difficulty by 50%&lt;/td&gt;
&lt;td&gt;&lt;a href="https://alova.js.org/tutorial/strategy/usePagination"&gt;usePagination&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Non-sense data interaction strategy&lt;/td&gt;
&lt;td&gt;A new interactive experience, submission and response, greatly reducing the impact of network fluctuations, allowing your application to still be available when the network is unstable or even disconnected&lt;/td&gt;
&lt;td&gt;&lt;a href="https://alova.js.org/tutorial/strategy/sensorless-data-interaction/overview"&gt;useSQRequest&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Form submission strategy&lt;/td&gt;
&lt;td&gt;A hook designed for form submission. Through this hook, you can easily implement form drafts and multi-page (multi-step) forms. In addition, it also provides common functions such as form reset&lt;/td&gt;
&lt;td&gt;&lt;a href="https://alova.js.org/tutorial/strategy/useForm"&gt;useForm&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;File upload strategy&lt;/td&gt;
&lt;td&gt;A simpler file upload strategy that supports automatic identification and conversion of base64, Blob, ArrayBuffer, and Canvas data&lt;/td&gt;
&lt;td&gt;&lt;a href="https://alova.js.org/tutorial/strategy/useUploader"&gt;useUploader&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Send verification code&lt;/td&gt;
&lt;td&gt;Verification code sending hook reduces the complexity of developing the verification code sending function.&lt;/td&gt;
&lt;td&gt;&lt;a href="https://alova.js.org/tutorial/strategy/useCaptcha"&gt;useCaptcha&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Automatically re-pull data&lt;/td&gt;
&lt;td&gt;Automatically re-pull data under certain conditions to ensure that the latest data is always displayed.&lt;/td&gt;
&lt;td&gt;&lt;a href="https://alova.js.org/tutorial/strategy/useAutoRequest"&gt;useAutoRequest&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Trigger requests across components&lt;/td&gt;
&lt;td&gt;An alova middleware that eliminates component-level restrictions and quickly triggers the operation function of any request in any component&lt;/td&gt;
&lt;td&gt;&lt;a href="https://alova.js.org/tutorial/strategy/actionDelegationMiddleware"&gt;actionDelegationMiddleware&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;UseRequest for serial requests&lt;/td&gt;
&lt;td&gt;A more concise and easy-to-use serial request use hook than &lt;a href="https://alova.js.org/tutorial/next-step/serial-request"&gt;alova's serial request method&lt;/a&gt;, providing a unified loading status, error, callback function&lt;/td&gt;
&lt;td&gt;&lt;a href="https://alova.js.org/tutorial/strategy/useSerialRequest"&gt;useSerialRequest&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;UseWatcher for serial requests&lt;/td&gt;
&lt;td&gt;A more concise and easy-to-use serial request use hook than &lt;a href="https://alova.js.org/tutorial/next-step/serial-request"&gt;alova's serial request method&lt;/a&gt;, providing a unified loading status, error, callback function.&lt;/td&gt;
&lt;td&gt;&lt;a href="https://alova.js.org/tutorial/strategy/useSerialWatcher"&gt;useSerialWatcher&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Request retry strategy&lt;/td&gt;
&lt;td&gt;Automatic retry on request failure, which plays an important role on important requests and polling requests&lt;/td&gt;
&lt;td&gt;&lt;a href="https://alova.js.org/tutorial/strategy/useRetriableRequest"&gt;useRetriableRequest&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;SSE requests&lt;/td&gt;
&lt;td&gt;Requests via Server-sent Events&lt;/td&gt;
&lt;td&gt;&lt;a href="https://alova.js.org/tutorial/strategy/useSSE"&gt;useSSE&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;For more in-depth learning about Alova, please visit the &lt;a href="https://alova.js.org/"&gt;Alova documentation&lt;/a&gt;. If you find Alova helpful, please star on &lt;a href="https://github.com/alovajs/alova"&gt;GitHub repository&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;If you find this article helpful, don't hesitate to like and comment. Share your thoughts on Alova or ask any questions you may have. Your support is our greatest motivation!&lt;/p&gt;

&lt;h3&gt;
  
  
  Join Our Community
&lt;/h3&gt;

&lt;p&gt;If you have any questions, you can join our community chat groups or start discussions on the &lt;a href="https://github.com/alovajs/alova/discussions"&gt;GitHub repository&lt;/a&gt;. If you encounter any issues, please submit them on &lt;a href="https://github.com/alovajs/alova/issues"&gt;GitHub's issues page&lt;/a&gt;, and we will address them promptly.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://discord.gg/S47QGJgkVb"&gt;Join our Discord community for discussions&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We also welcome contributions. For more information, please visit our &lt;a href="https://alova.js.org/contributing/overview"&gt;contribution guidelines&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>react</category>
      <category>vue</category>
      <category>svelte</category>
    </item>
    <item>
      <title>Data prefetch of alovajs, a request strategy library</title>
      <dc:creator>Scott Hu</dc:creator>
      <pubDate>Thu, 09 Nov 2023 08:42:32 +0000</pubDate>
      <link>https://dev.to/coderhu/data-prefetch-of-alovajs-a-request-strategy-library-42ej</link>
      <guid>https://dev.to/coderhu/data-prefetch-of-alovajs-a-request-strategy-library-42ej</guid>
      <description>&lt;p&gt;Alova is a lightweight request strategy library designed to simplify interface management and usage. It consists of 2 parts:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Declarative implementation of complex requests:&lt;/strong&gt; You can implement complex requests such as request sharing, pagination, form submission, breakpoint resume, etc. by simply configuring parameters without writing a lot of code, improving development efficiency and application performance and reduce pressure on the server.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;API automatic management and maintenance:&lt;/strong&gt; You no longer need to define the request functions by yourself, and you no longer need to consult the API documentation. alova can help you generate a complete and detailed TypeScript type of the request function, so that the front-end project can be integrated with the server-side seamless. When the server-side API is updated, the front-end project will also be notified and the project will be blocked from publishing.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://alova.js.org/category/examples"&gt;There are many runnable examples here&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;With Alova, all you need to do is select the appropriate useHook for your requests, now it support &lt;code&gt;React&lt;/code&gt;, &lt;code&gt;Vue&lt;/code&gt;, and &lt;code&gt;Svelte&lt;/code&gt;. If you find alova helpful, please consider star on &lt;a href="https://github.com/alovajs/alova"&gt;GitHub repository&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Join Our Community
&lt;/h2&gt;

&lt;p&gt;If you have any questions or need assistance, you can join our communication or start a discussion on &lt;a href="https://github.com/alovajs/alova/discussions"&gt;GitHub repository&lt;/a&gt; for support. If you encounter any issues, please submit them on &lt;a href="https://github.com/alovajs/alova/issues"&gt;GitHub issues&lt;/a&gt;, and we'll address them as soon as possible.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://discord.gg/S47QGJgkVb"&gt;Join Discord&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We also welcome contributions. For more information, please visit &lt;a href="https://alova.js.org/contributing/overview"&gt;contribution guidelines&lt;/a&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;For tutorials and more on how to use Alova, feel free to explore the &lt;a href="https://alova.js.org/"&gt;alova documentation&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Data fetch
&lt;/h2&gt;

&lt;p&gt;When you have the following needs:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Preload the data that will be used in the subsequent process and store it in the cache, so that users no longer wait for the data loading process;&lt;/li&gt;
&lt;li&gt;It is convenient to update data across pages (similar to the global state), for example, after modifying an item in the todo list and re-fetching the latest data, the interface will be refreshed after the response.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;code&gt;useFetcher&lt;/code&gt; is the hook used to implement the above scenarios. The response data obtained through it cannot be received directly, but the data fetched through it will not only update the cache, but also update the corresponding state, thereby re-rendering the view.&lt;/p&gt;

&lt;p&gt;You can use it to pre-fetch data and save it in the cache, or gracefully update the state across components, such as modifying an item in the todo list and re-fetching the latest data, and the interface will be refreshed after the response&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;the following code is used react.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Update views across modules/components
&lt;/h3&gt;

&lt;p&gt;Next, let's modify a certain todo data, and re-fetch the latest todo list data to update the view.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;getTodoList&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;currentPage&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;alovaInstance&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/todo/list&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Note: The name attribute is set here to filter out the required Method instance when the Method instance cannot be specified directly&lt;/span&gt;
    &lt;span class="c1"&gt;// For details, see the subsequent "Method Instance Matcher" chapter&lt;/span&gt;
    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;todoList&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;params&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;currentPage&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;pageSize&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;App&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// The fetching attribute is the same as loading, it is true when a fetch request is sent, and it is false after the request ends&lt;/span&gt;
    &lt;span class="nx"&gt;fetching&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;onSuccess&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;onError&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;onComplete&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;

    &lt;span class="c1"&gt;// After calling fetch, a request to fetch data will be sent, and fetch can be called repeatedly to fetch data from different interfaces&lt;/span&gt;
    &lt;span class="nx"&gt;fetch&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useFetcher&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

  &lt;span class="c1"&gt;// Trigger the data fetch in the event&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;handleSubmit&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Assume the modification of the todo item has been completed...&lt;/span&gt;

    &lt;span class="c1"&gt;// Start to fetch the updated data&lt;/span&gt;
    &lt;span class="c1"&gt;// Situation 1: When you clearly know that the data on the first page of todoList is fetched, pass in a Method instance&lt;/span&gt;
    &lt;span class="nx"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;getTodoList&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;

    &lt;span class="c1"&gt;// Situation 2: When you only know to fetch the last requested data of todoList, use the Method instance matcher to filter&lt;/span&gt;
    &lt;span class="nx"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;todoList&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;method&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;index&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;ary&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// Return true to specify the Method instance that needs to be fetched&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;index&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;ary&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&amp;gt;&lt;/span&gt;
      &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="cm"&gt;/* Render the unified fetch state */&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
      &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;fetching&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Fetching data in the background...&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
      &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="cm"&gt;/* ... */&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt; &lt;span class="na"&gt;onClick&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;handleSubmit&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Modify todo items&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;See &lt;a href="https://alova.js.org/tutorial/next-step/method-instance-matcher"&gt;Method instance matcher&lt;/a&gt; for more usage methods of &lt;code&gt;Method&lt;/code&gt; instance matcher&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  preload data
&lt;/h3&gt;

&lt;p&gt;The following implements the preloading function of the next page of data in the paging scenario of the todo list.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useState&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// method instance creation function&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;getTodoList&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;currentPage&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;alovaInstance&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/todo/list&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;params&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;currentPage&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;pageSize&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;App&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;fetch&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useFetcher&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;currentPage&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setCurrentPage&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;onSuccess&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useWatcher&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;getTodoList&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;currentPage&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;currentPage&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;immediate&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="c1"&gt;// Pre-fetch the data of the next page when the current page request is successful&lt;/span&gt;
  &lt;span class="c1"&gt;// Realize that there is no need to wait for the request when turning the page to the next page&lt;/span&gt;
  &lt;span class="nx"&gt;onSuccess&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;getTodoList&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;currentPage&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="cm"&gt;/* ... */&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Notes: After the useFetcher request is completed, only the cache is updated, and if it is found that there is still a &lt;code&gt;data&lt;/code&gt; state under the &lt;code&gt;Method&lt;/code&gt; instance, it will also be updated synchronously, so as to ensure that the page data is consistent. This is &lt;code&gt;useFetcher&lt;/code&gt; used to update views across modules/components ensure.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Compare with useRequest and useWatcher
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;useFetcher does not return the &lt;code&gt;data&lt;/code&gt; field, the pre-fetched data will be saved in the cache, and the status data of the corresponding location will be updated;&lt;/li&gt;
&lt;li&gt;Rename &lt;code&gt;loading&lt;/code&gt; to &lt;code&gt;fetching&lt;/code&gt;;&lt;/li&gt;
&lt;li&gt;There is no &lt;code&gt;send&lt;/code&gt; function, but there is a &lt;code&gt;fetch&lt;/code&gt; function, which can be reused to fetch data from different interfaces. At this time, you can use the &lt;code&gt;fetching&lt;/code&gt; and &lt;code&gt;error&lt;/code&gt; states to render views uniformly, so as to achieve unified processing the goal of;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  (End)Why Use Alova
&lt;/h2&gt;

&lt;p&gt;Alova is committed to addressing client-side network request challenges, but what sets it apart from other request libraries is its focus on business-scenario-driven request strategies. When used in conjunction with libraries like &lt;code&gt;axios/fetch api&lt;/code&gt;, Alova can meet 99% of your request needs while offering a range of advanced features.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;You may have pondered over whether to encapsulate &lt;code&gt;fetch&lt;/code&gt; and &lt;code&gt;axios&lt;/code&gt;, but now you no longer need to. With Alova, you can use a declarative approach to fulfill complex requests, including request sharing, pagination, form submissions, and resumable uploads, as well as automated cache management, request sharing, and cross-component state updates.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Alova is lightweight, occupying only 4kb+, which is just over 30% of Axios's size.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;It currently supports &lt;code&gt;vue/react/react-native/svelte&lt;/code&gt; and SSR frameworks like &lt;code&gt;next/nuxt/sveltekit&lt;/code&gt;, as well as cross-platform frameworks like &lt;code&gt;Uniapp/Taro&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Alova is loosely coupled, allowing you to use it in any JavaScript environment with any UI framework using different adapters. It offers a unified user experience and seamless code migration.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Alova also promotes a highly organized approach for aggregating API code, grouping request parameters, cache behavior, and response data transformations in the same code blocks, which is advantageous for managing numerous APIs.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://alova.js.org/tutorial/get-started/comparison"&gt;Compare Alova with other request libraries&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Multi-Framework Support
&lt;/h2&gt;

&lt;p&gt;Now, you can perfectly use Alova in &lt;a href="https://vuejs.org/guide/introduction.html#api-styles"&gt;vue options (vue2 and vue3) syntax&lt;/a&gt;. In the future, we plan to support the following frameworks:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Functional ones like &lt;code&gt;solid/preact/qwik&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Class-based ones like &lt;code&gt;angular/lit/stencil&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Options-based ones like &lt;code&gt;native Chinese mini-programs&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Alova also offers powerful request strategies:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Name&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;th&gt;Documentation&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Pagination request strategy&lt;/td&gt;
&lt;td&gt;Automatically manage paging data, data preloading, reduce unnecessary data refresh, improve fluency by 300%, and reduce coding difficulty by 50%&lt;/td&gt;
&lt;td&gt;&lt;a href="https://alova.js.org/tutorial/strategy/usePagination"&gt;usePagination&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Non-sense data interaction strategy&lt;/td&gt;
&lt;td&gt;A new interactive experience, submission and response, greatly reducing the impact of network fluctuations, allowing your application to still be available when the network is unstable or even disconnected&lt;/td&gt;
&lt;td&gt;&lt;a href="https://alova.js.org/tutorial/strategy/sensorless-data-interaction/overview"&gt;useSQRequest&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Form submission strategy&lt;/td&gt;
&lt;td&gt;A hook designed for form submission. Through this hook, you can easily implement form drafts and multi-page (multi-step) forms. In addition, it also provides common functions such as form reset&lt;/td&gt;
&lt;td&gt;&lt;a href="https://alova.js.org/tutorial/strategy/useForm"&gt;useForm&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;File upload strategy&lt;/td&gt;
&lt;td&gt;A simpler file upload strategy that supports automatic identification and conversion of base64, Blob, ArrayBuffer, and Canvas data&lt;/td&gt;
&lt;td&gt;&lt;a href="https://alova.js.org/tutorial/strategy/useUploader"&gt;useUploader&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Send verification code&lt;/td&gt;
&lt;td&gt;Verification code sending hook reduces the complexity of developing the verification code sending function.&lt;/td&gt;
&lt;td&gt;&lt;a href="https://alova.js.org/tutorial/strategy/useCaptcha"&gt;useCaptcha&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Automatically re-pull data&lt;/td&gt;
&lt;td&gt;Automatically re-pull data under certain conditions to ensure that the latest data is always displayed.&lt;/td&gt;
&lt;td&gt;&lt;a href="https://alova.js.org/tutorial/strategy/useAutoRequest"&gt;useAutoRequest&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Trigger requests across components&lt;/td&gt;
&lt;td&gt;An alova middleware that eliminates component-level restrictions and quickly triggers the operation function of any request in any component&lt;/td&gt;
&lt;td&gt;&lt;a href="https://alova.js.org/tutorial/strategy/actionDelegationMiddleware"&gt;actionDelegationMiddleware&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;UseRequest for serial requests&lt;/td&gt;
&lt;td&gt;A more concise and easy-to-use serial request use hook than &lt;a href="https://alova.js.org/tutorial/next-step/serial-request"&gt;alova's serial request method&lt;/a&gt;, providing a unified loading status, error, callback function&lt;/td&gt;
&lt;td&gt;&lt;a href="https://alova.js.org/tutorial/strategy/useSerialRequest"&gt;useSerialRequest&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;UseWatcher for serial requests&lt;/td&gt;
&lt;td&gt;A more concise and easy-to-use serial request use hook than &lt;a href="https://alova.js.org/tutorial/next-step/serial-request"&gt;alova's serial request method&lt;/a&gt;, providing a unified loading status, error, callback function.&lt;/td&gt;
&lt;td&gt;&lt;a href="https://alova.js.org/tutorial/strategy/useSerialWatcher"&gt;useSerialWatcher&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Request retry strategy&lt;/td&gt;
&lt;td&gt;Automatic retry on request failure, which plays an important role on important requests and polling requests&lt;/td&gt;
&lt;td&gt;&lt;a href="https://alova.js.org/tutorial/strategy/useRetriableRequest"&gt;useRetriableRequest&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;SSE requests&lt;/td&gt;
&lt;td&gt;Requests via Server-sent Events&lt;/td&gt;
&lt;td&gt;&lt;a href="https://alova.js.org/tutorial/strategy/useSSE"&gt;useSSE&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;For more in-depth learning about Alova, please visit the &lt;a href="https://alova.js.org/"&gt;Alova documentation&lt;/a&gt;. If you find Alova helpful, please star on &lt;a href="https://github.com/alovajs/alova"&gt;GitHub repository&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;If you find this article helpful, don't hesitate to like and comment. Share your thoughts on Alova or ask any questions you may have. Your support is our greatest motivation!&lt;/p&gt;

&lt;h3&gt;
  
  
  Join Our Community
&lt;/h3&gt;

&lt;p&gt;If you have any questions, you can join our community chat groups or start discussions on the &lt;a href="https://github.com/alovajs/alova/discussions"&gt;GitHub repository&lt;/a&gt;. If you encounter any issues, please submit them on &lt;a href="https://github.com/alovajs/alova/issues"&gt;GitHub's issues page&lt;/a&gt;, and we will address them promptly.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://discord.gg/S47QGJgkVb"&gt;Join our Discord community for discussions&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We also welcome contributions. For more information, please visit our &lt;a href="https://alova.js.org/contributing/overview"&gt;contribution guidelines&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>react</category>
      <category>vue</category>
      <category>svelte</category>
    </item>
  </channel>
</rss>
