最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

JavaScript 中斷請(qǐng)求幾種方案詳解

 更新時(shí)間:2021年09月09日 14:37:27   作者:想成為大佬的鴨子  
這篇文章主要介紹了JavaScript 中斷請(qǐng)求幾種方案詳解,本篇文章通過(guò)簡(jiǎn)要的案例,講解了該項(xiàng)技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下

1 Promise

Promise有一個(gè)缺點(diǎn)是一旦創(chuàng)建無(wú)法取消,所以本質(zhì)上Promise是無(wú)法被終止的.

但是我們可以通過(guò)中斷調(diào)用鏈或中斷Promise來(lái)模擬請(qǐng)求的中斷.

中斷調(diào)用鏈

中斷調(diào)用鏈就是在某一個(gè)then/catch執(zhí)行之后,后續(xù)的鏈?zhǔn)秸{(diào)用(包括then,catch,finally)不再繼續(xù)執(zhí)行.

方法是在then/catch返回一個(gè)新的Promise實(shí)例,并保持pending狀態(tài):

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

中斷Promise

中斷Promise不等同于中止Promise,因?yàn)镻romise是無(wú)法被終止的.

這里的中斷指的是,在合適的時(shí)機(jī),把pending狀態(tài)的promise給reject掉.例如一個(gè)常見(jiàn)的應(yīng)用場(chǎng)景就是給網(wǎng)絡(luò)請(qǐng)求設(shè)置超時(shí)時(shí)間,一旦超時(shí)就中斷.

老規(guī)矩,用setTimeout來(lái)模擬網(wǎng)絡(luò)請(qǐng)求.閥值設(shè)置為Math.random() * 3000表示隨機(jī)3秒之內(nèi)返回結(jié)果.

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

假設(shè)超過(guò)2秒就是網(wǎng)絡(luò)超時(shí),我們可以封裝一個(gè)超時(shí)處理函數(shù).

由于網(wǎng)絡(luò)請(qǐng)求所需的事件是隨機(jī)的,因此可以利用Promise.race方法,達(dá)到超時(shí)reject的目的.

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

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

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

上面實(shí)現(xiàn)的方式并不靈活,因?yàn)橹袛郟romise的方式有很多,不單單是網(wǎng)絡(luò)超時(shí).

我們可以仿照Axios中CancelToken的核心源碼,簡(jiǎn)單包裝一個(gè)abort方法,供使用者隨時(shí)調(diào)用.

function abortWrapper(p1) {
    let abort;
    const p2 = new Promise((resolve, reject) => {
        abort = reject;
    });
    // 如果沒(méi)有resolve或reject,p2的狀態(tài)永遠(yuǎn)是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(() => {
    // 手動(dòng)調(diào)用req.abort,將p2的狀態(tài)改變?yōu)閞ejected
    req.abort('手動(dòng)中斷請(qǐng)求');
}, 2000);

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

需要注意的是,雖然Promise請(qǐng)求被中斷了,但是promise并沒(méi)有終止,網(wǎng)絡(luò)請(qǐng)求依然可能返回,只不過(guò)那時(shí)我們已經(jīng)不關(guān)心請(qǐng)求結(jié)果了.

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;

// 創(chuàng)建一個(gè)變量如 cancel 用于存儲(chǔ)這個(gè)中斷某個(gè)請(qǐng)求的方法
let cancel;

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

// 判斷 cancel 是否為函數(shù),確保 axios 已實(shí)例化一個(gè)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的核心源碼所體現(xiàn)的思想,與上面中斷Promise包裝abort方法的思想一致.

只不過(guò)Axios在外部手動(dòng)調(diào)用resolve(用戶觸發(fā)cancel方法),而resolve一旦調(diào)用,就會(huì)觸發(fā)promise的then方法,來(lái)看這個(gè)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方法中會(huì)執(zhí)行abort方法取消請(qǐng)求,同時(shí)調(diào)用reject讓外層的promise失敗.

到此這篇關(guān)于JavaScript 中斷請(qǐng)求幾種方案詳解的文章就介紹到這了,更多相關(guān)js中斷請(qǐng)求內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • JS判斷微信掃碼的方法

    JS判斷微信掃碼的方法

    這篇文章通過(guò)代碼給大家介紹了JS判斷是否是微信掃碼的方法,非常不錯(cuò),需要的朋友參考下吧
    2017-08-08
  • JS中confirm,alert,prompt函數(shù)使用區(qū)別分析

    JS中confirm,alert,prompt函數(shù)使用區(qū)別分析

    JS中confirm,alert,prompt函數(shù)使用區(qū)別分析,需要的朋友可以參考下。
    2010-04-04
  • javascript 最常用的10個(gè)自定義函數(shù)[推薦]

    javascript 最常用的10個(gè)自定義函數(shù)[推薦]

    如果不使用類庫(kù)或者沒(méi)有自己的類庫(kù),儲(chǔ)備一些常用函數(shù)總是有好處的。
    2009-12-12
  • js中判斷控件是否存在

    js中判斷控件是否存在

    在動(dòng)態(tài)頁(yè)面中,頁(yè)面中包含一些動(dòng)態(tài)產(chǎn)生的控件,在有些情況下需要判斷動(dòng)態(tài)生成的控件是否存在。
    2010-08-08
  • 真見(jiàn)識(shí)了-全代碼編寫的圖片

    真見(jiàn)識(shí)了-全代碼編寫的圖片

    真見(jiàn)識(shí)了-全代碼編寫的圖片...
    2007-08-08
  • js觀察者模式的彈幕案例

    js觀察者模式的彈幕案例

    這篇文章主要為大家詳細(xì)介紹了js觀察者模式的彈幕案例,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2020-11-11
  • js中為什么Proxy一定要配合Reflect使用

    js中為什么Proxy一定要配合Reflect使用

    大多數(shù)開(kāi)發(fā)者都了解這兩個(gè)?Es6?中的新增內(nèi)置模塊,可是你也許并不清楚為什么?Proxy?一定要配合?Reflect?使用,本文主要介紹了js中為什么Proxy一定要配合Reflect使用,感興趣的可以了解一下
    2022-04-04
  • 微信小程序自定義Dialog彈框

    微信小程序自定義Dialog彈框

    這篇文章主要為大家詳細(xì)介紹了微信小程序自定義Dialog彈框,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-07-07
  • ES6 系列之 Generator 的自動(dòng)執(zhí)行的方法示例

    ES6 系列之 Generator 的自動(dòng)執(zhí)行的方法示例

    這篇文章主要介紹了ES6 系列之 Generator 的自動(dòng)執(zhí)行的方法示例,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2018-10-10
  • 利用用JS實(shí)現(xiàn)一個(gè)實(shí)時(shí)小鬧鐘

    利用用JS實(shí)現(xiàn)一個(gè)實(shí)時(shí)小鬧鐘

    天我們來(lái)聊聊如何使用JS來(lái)創(chuàng)建一個(gè)實(shí)時(shí)的小鬧鐘,這個(gè)小鬧鐘十分的有趣,小伙伴們可以運(yùn)行一下,看看跟你電腦上的時(shí)間是否對(duì)的上呢,文章通過(guò)代碼示例介紹的非常詳細(xì),需要的朋友可以參考下
    2023-11-11

最新評(píng)論

交城县| 诏安县| 富民县| 山西省| 离岛区| 平江县| 册亨县| 绥中县| 镇宁| 揭阳市| 舟山市| 乐都县| 合山市| 扎兰屯市| 屏东市| 龙山县| 内丘县| 庐江县| 白山市| 大丰市| 来安县| 雅江县| 黎平县| 灵山县| 纳雍县| 正阳县| 连平县| 上犹县| 永安市| 莱州市| 金山区| 宜兰市| 惠来县| 阳山县| 阳高县| 阳朔县| 寿宁县| 长海县| 上林县| 永德县| 姜堰市|