91超碰碰碰碰久久久久久综合_超碰av人澡人澡人澡人澡人掠_国产黄大片在线观看画质优化_txt小说免费全本

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

JavaScript如何中斷請求

發布時間:2021-09-09 16:39:11 來源:億速云 閱讀:204 作者:小新 欄目:開發技術

這篇文章給大家分享的是有關JavaScript如何中斷請求的內容。小編覺得挺實用的,因此分享給大家做個參考,一起跟隨小編過來看看吧。

1 Promise

Promise有一個缺點是一旦創建無法取消,所以本質上Promise是無法被終止的.

但是我們可以通過中斷調用鏈或中斷Promise來模擬請求的中斷.

中斷調用鏈

中斷調用鏈就是在某一個then/catch執行之后,后續的鏈式調用(包括then,catch,finally)不再繼續執行.

方法是在then/catch返回一個新的Promise實例,并保持pending狀態:

new Promise((resolve, reject) => {
    setTimeout(() => {
        resolve('result');
    });
}).then(res => {
    // 達到某種條件,return一個pending狀態的Promise實例,以中斷調用鏈
    if (res === 'result') {
        return new Promise(() => {});
    }
    console.log(res); // 不打印
}).then(() => {
    console.log('then不執行'); // 不打印
}).catch(() => {
    console.log('catch不執行'); // 不打印
}).finally(() => {
    console.log('finally不執行'); // 不打印
});

中斷Promise

中斷Promise不等同于中止Promise,因為Promise是無法被終止的.

這里的中斷指的是,在合適的時機,把pending狀態的promise給reject掉.例如一個常見的應用場景就是給網絡請求設置超時時間,一旦超時就中斷.

老規矩,用setTimeout來模擬網絡請求.閥值設置為Math.random() * 3000表示隨機3秒之內返回結果.

const request = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve('收到服務端數據')
  }, Math.random() * 3000)
})

假設超過2秒就是網絡超時,我們可以封裝一個超時處理函數.

由于網絡請求所需的事件是隨機的,因此可以利用Promise.race方法,達到超時reject的目的.

const timeoutReject = (p1, timeout = 2000) => {
    const p2 = new Promise((resolve, reject) => {
        setTimeout(() => {
            reject('網絡超時');
        }, timeout);
    });
    return Promise.race([p1, p2]);
};

timeoutReject(request).then(res => {
    console.log(res);
}).catch(err => {
    console.log(err);
});

包裝abort方法——仿照Axios的CancelToken

上面實現的方式并不靈活,因為中斷Promise的方式有很多,不單單是網絡超時.

我們可以仿照Axios中CancelToken的核心源碼,簡單包裝一個abort方法,供使用者隨時調用.

function abortWrapper(p1) {
    let abort;
    const p2 = new Promise((resolve, reject) => {
        abort = reject;
    });
    // 如果沒有resolve或reject,p2的狀態永遠是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(() => {
    // 手動調用req.abort,將p2的狀態改變為rejected
    req.abort('手動中斷請求');
}, 2000);

如此封裝的主要目的就是為了能夠在Promise外部控制其resolve或reject,讓使用者可以隨時手動調用resolve(觸發.then)或reject(觸發.catch).

需要注意的是,雖然Promise請求被中斷了,但是promise并沒有終止,網絡請求依然可能返回,只不過那時我們已經不關心請求結果了.

2 RXJS的unsubscribe方法

rxjs本身提供了取消訂閱的方法,即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);

3 Axios的CancelToken

Axios的CancelToken有兩種使用方法:

  • 方法一

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.');
  • 方法二

import axios from 'axios';
const CancelToken = axios.CancelToken;

// 創建一個變量如 cancel 用于存儲這個中斷某個請求的方法
let cancel;

axios.get('/user/12345', {
  cancelToken: new CancelToken(function executor(c) {
    cancel = c; // 將參數 c 賦值給 cancel
  })
});

// 判斷 cancel 是否為函數,確保 axios 已實例化一個CancelToken
if (typeof cancel === 'function') {
    cancel();
    cancel = null;
}

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) {
      // 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;

可以看到,在Axios底層,CancelToken的核心源碼所體現的思想,與上面中斷Promise包裝abort方法的思想一致.

只不過Axios在外部手動調用resolve(用戶觸發cancel方法),而resolve一旦調用,就會觸發promise的then方法,來看這個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;
  });
}

可以看到then方法中會執行abort方法取消請求,同時調用reject讓外層的promise失敗.

感謝各位的閱讀!關于“JavaScript如何中斷請求”這篇文章就分享到這里了,希望以上內容可以對大家有一定的幫助,讓大家可以學到更多知識,如果覺得文章不錯,可以把它分享出去讓更多的人看到吧!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

大冶市| 阳谷县| 高邮市| 亚东县| 稷山县| 卓资县| 东港市| 阿拉善盟| 巴彦淖尔市| 淮北市| 法库县| 四平市| 斗六市| 万山特区| 桑植县| 定州市| 陆良县| 大庆市| 岳池县| 大同市| 宿州市| 当雄县| 黔南| 松溪县| 红原县| 墨玉县| 晋州市| 吕梁市| 满城县| 姚安县| 贵港市| 盱眙县| 临城县| 凭祥市| 长宁区| 陵水| 永州市| 泗阳县| 石楼县| 莫力| 内黄县|