Get the App
SLTechnology News&Howtos  ›  Development  › 

How JavaScript interrupts the request

Shulou Source: shulou.com Published: 2022-06-03 16:36:41 09月11日 Update

This article is about how JavaScript interrupts requests. The editor thinks it is very practical, so share it with you as a reference and follow the editor to have a look.

1 Promise

One disadvantage of Promise is that once it is created, it cannot be cancelled, so Promise cannot be terminated in nature.

But we can simulate the requested interrupt by interrupting the call chain or interrupting the Promise.

Interrupt call chain

Interrupt call chain means that after a then/catch is executed, subsequent chain calls (including then,catch,finally) no longer execute.

The way to do this is to return a new Promise instance in then/catch and keep the pending state:

New Promise ((resolve, reject) = > {setTimeout (() = > {resolve ('result');});}) then (res = > {/ / return a Promise instance in pending state to interrupt the call chain if (res = =' result') {return new Promise (() = > {});} console.log (res) / / do not print}). Then (() = > {console.log ('then does not execute'); / / do not print}). Catch () = > {console.log ('catch do not execute'); / / do not print}). Finally () = > {console.log ('finally do not execute'); / / do not print}); interrupt Promise

Interrupting Promise is not the same as aborting Promise, because Promise cannot be terminated.

The interrupt here refers to giving the promise of the pending status to the reject at the right time. For example, a common application scenario is to set a timeout for network requests, which will be interrupted once the timeout occurs.

The old rule is to use setTimeout to simulate network requests. Setting the threshold to Math.random () * 3000 means that the result is randomly returned within 3 seconds.

Const request = new Promise ((resolve, reject) = > {setTimeout (()) = > {resolve ('receiving server data')}, Math.random () * 3000)})

Assuming that more than 2 seconds is a network timeout, we can encapsulate a timeout handler.

Because the events required for network requests are random, the Promise.race method can be used to achieve the purpose of timeout reject.

Const timeoutReject = (p1, timeout = 2000) = > {const p2 = new Promise ((resolve, reject) = > {setTimeout (()) = > {reject ('network timeout');}, timeout);}); return Promise.race ([p1, p2]);}; timeoutReject (request) .then (res = > {console.log (res);}) .catch (err = > {console.log (err);}) Packaging abort method-- imitating Axios's CancelToken

The above implementation is not flexible, because there are many ways to interrupt Promise, not just network timeout.

We can emulate the core source code of CancelToken in Axios and simply wrap an abort method for users to call at any time.

Function abortWrapper (p1) {let abort; const p2 = new Promise ((resolve, reject) = > {abort = reject;}); / / if there is no resolve or reject,p2, the state is always pending const p = Promise.race ([p1, p2]); p.abort = abort; return p;} const req = abortWrapper (request); req.then (res = > {console.log (res);}) .catch (err = > {console.log (err) }); setTimeout (() = > {/ / manually call req.abort to change the status of p2 to rejected req.abort ('manual interrupt request');}, 2000)

The main purpose of this encapsulation is to be able to control its resolve or reject outside the Promise, so that the user can call resolve (trigger. Then) or reject (trigger. Catch) at any time.

It should be noted that although the Promise request is interrupted, the promise is not terminated, and the network request may still return, but at that time we no longer care about the result of the request.

2 unsubscribe method of RXJS

Rxjs itself provides a way to unsubscribe, that is, unsubscribe.

Let stream1 $= new Observable (observer = > {let timeout = setTimeout (()) > {observer.next ('observable timeout');}, 2000); return () = > {clearTimeout (timeout);}}); let disposable = stream1 $.subscribe (value = > console.log (value)); setTimeout (() = > {disposable.unsubscribe ();}, 1000); CancelToken of 3 Axios

There are two ways to use Axios's CancelToken:

Method one

Import axios from 'axios';const CancelToken = axios.CancelToken;const source = CancelToken.source (); axios.get (' / user/12345', {cancelToken: source.token}) .catch (function (thrown) {if (axios.isCancel (thrown)) {console.log ('Request canceled', thrown.message);} else {/ / handle error}}); source.cancel (' Operation canceled by the user.')

Method two

Import axios from 'axios';const CancelToken = axios.CancelToken;// create a variable such as cancel to store the method let cancel;axios.get (' / user/12345', {cancelToken: new CancelToken (function executor (c) {cancel = c; / / assign parameter c to cancel})}; / / determine whether cancel is a function and make sure that axios has instantiated a CancelTokenif (typeof cancel = 'function') {cancel () Cancel = null;}

Core source code of CancelToken: (axios/lib/cancel/CancelToken.js)

'use strict';var Cancel = require ('. / Cancel'); / * * A `CancelToken` is an object that can be used to request cancellation of an operation. * * @ class * @ param {Function} executor The executor function. * / function CancelToken (executor) {if (typeof executor! = = 'function') {throw new TypeError (' executor must be a function.');} var resolvePromise; this.promise = new Promise (function promiseExecutor (resolve) {resolvePromise = resolve;}); var token = this; executor (function cancel (message) {if (token.reason) {if (token.reason) {/ / Cancellation has already been requested return;} token.reason = new Cancel (message) ResolvePromise (token.reason);});} / * Throws a `Cancel` if cancellation has been requested. * / CancelToken.prototype.throwIfRequested = function throwIfRequested () {if (this.reason) {throw this.reason;}}; / * Returns an object that contains a new `CancelToken` and a function that, when called, * cancels the `CancelToken`. * / CancelToken.source = function source () {var cancel; var token = new CancelToken (function executor (c) {cancel = c;}); return {token: token, cancel: cancel};}; module.exports = CancelToken

As you can see, at the bottom of Axios, the core source code of CancelToken is consistent with the idea of interrupting Promise wrapping abort above.

It's just that Axios manually calls resolve (the user triggers the cancel method) outside, and once resolve is called, it will trigger the then method of promise to see the source code of this promise.then: (axios/lib/adapters/xhr.js)

If (config.cancelToken) {/ / Handle cancellation config.cancelToken.promise.then (function onCanceled (cancel) {if (! request) {return;} request.abort (); reject (cancel); / / Clean up request request = null;});}

You can see that the then method executes the abort method to cancel the request, while calling reject causes the outer promise to fail.

Thank you for reading! This is the end of the article on "how to interrupt the request for JavaScript". I hope the above content can be of some help to you, so that you can learn more knowledge. if you think the article is good, you can share it for more people to see!

Tags: Method network state that is manual source code instance core wrapper user content function but thought way more purpose article result encapsulation Apple Docker Huawei Linux macOS MariaDB Microsoft MySQL NVidia OPPO Reno OPPO Reno MariaDB Redmi Shulou Information Microsoft