• 首页 首页 icon
  • 工具库 工具库 icon
    • IP查询 IP查询 icon
  • 内容库 内容库 icon
    • 快讯库 快讯库 icon
    • 精品库 精品库 icon
    • 问答库 问答库 icon
  • 更多 更多 icon
    • 服务条款 服务条款 icon

前端小课堂—— 取消ajax请求

武飞扬头像
你看那儿有阳光在飞
帮助1

这篇文章简单讨论一下,如何取消一个ajax请求。

一、取消ajax请求的场景

开发过程中,遇到需要取消ajax请求的场景有很多,例如:

  • 请求超时,为了不影响用户体验,前端主动取消ajax请求;
  • 页面转换,取消前一个页面尚未响应的ajax请求;
  • 频繁发送请求的场景,取消前一个尚未响应的ajax请求,也就是所谓的防抖;

二、前端ajax请求的方式及终止取消

前端ajax请求是应用最频繁的操作。目前浏览器支持的ajax请求api主要有两种,XMLHttpRequest和Fetch API。除此之外,需要关注的就是第三方请求库了。最主要的包括jquery ajax和axios,前者在目前的前端开发模式中,已经很少使用了。所以,我们只讨论第三方请求库axios。

1、XMLHttpRequest请求的终止取消

XMLHttpRequest对象用于与服务器交互。通过 XMLHttpRequest 可以在不刷新页面的情况下请求特定 URL,获取数据。因而可以在不影响用户操作的情况下,更新页面的局部内容。

发送一个 HTTP 请求,需要创建一个XMLHttpRequest对象,打开一个 URL,最后发送请求。当所有这些事务完成后,该对象将会包含一些诸如响应主体或 HTTP status 的有用信息。

function onload () {
  console.log(this.responseText)
}

const xhr = new XMLHttpRequest()
xhr.addEventListener("load", onload)
xhr.open('GET', 'http://127.0.0.1:4523/mock/797249/goods/list', true)
xhr.send()

取消终止该请求,需要用到XMLHttpRequest.abort() 方法。当一个请求被终止,它的readyState将被置为 XMLHttpRequest.UNSENT(0),并且请求的 status 置为 0。

setTimeout(() => {  
    xhr.abort()
}, 1000)

学新通

此时的readyState和status:

学新通

2、Fetch API请求的终止取消

Fetch API提供了一个JavaScript接口,用于访问和操作http请求协议,如请求和响应。并且还提供了一个全局异步获取资源的fetch()方法,不同于XMLHttpRequest,Fetch是基于Promise,使用更加简单,而且更合乎异步请求逻辑。并且还可以方便的service workers中使用。Fetch还集成了很多HTTP概念,例如:CORS,credentials和其他HTTP扩展等

fetch(`http://127.0.0.1:4523/mock/797249/goods/list?keyword=包包`, {
  method: 'GET', 
  headers: {
    'Content-Type': 'application/json',
  },
  body: ''
})
.then(response => response.json())
.then(data => {
  console.log('Success:', data);
})
.catch((error) => {
  console.error('Error:', error);
})

终止取消fetch请求,需要用到AbortController 和 AbortSignal

  • 1、创建AbortController实例controller
  • 2、使用 controller.signal属性,获取到AbortSignal实例signal
  • 3、通过fetch方法的第二个参数选项signal,跟fetch请求关联
  • 4、使用controller.abort()方法,终止取消fetch请求
const controller = new AbortController()
const signal = controller.signal

fetch(`http://127.0.0.1:4523/mock/797249/goods/list?keyword=包包`, {
    signal,
    // ...
})

// 终止取消
controller.abort()

结果会打印以下异常

Error: DOMException: The user aborted a request.

此时的signal状态

学新通

controller.abort()接受一个参数,作为终止请求的reason:

// 终止取消
controller.abort('请求超时')

此时的signal状态

学新通

3、axios请求的终止取消

Axios 是一个基于 promise 的 HTTP 库,可以用在浏览器和 node.js 中。在服务端它使用原生 node.js http 模块, 而在客户端 (浏览端) 则使用 XMLHttpRequests。

使用用例:

axios.get('http://127.0.0.1:4523/mock/797249/goods/list?keyword=包包')
    .then(function (response) { 
        // 处理成功情况 
        console.log(response); 
    }) 
    .catch(function (error) { 
        // 处理错误情况 
        console.log(error); 
    })

有两种方式可以终止取消axios请求:

  • 从 v0.22.0 开始,Axios 支持以 fetch API 方式—— AbortController 取消请求
const controller = new AbortController()

axios.get('http://127.0.0.1:4523/mock/797249/goods/list?keyword=包包',{
    signal: controller.signal
}).then(function (response) { 
    // 处理成功情况 
    console.log(response); 
}).catch(function (error) { 
    // 处理错误情况 
    console.log(error); 
})

// 取消请求 
controller.abort()
  • 使用 cancel token 取消一个请求,此 API 从 v0.22.0 开始已被弃用
const CancelToken = axios.CancelToken
const source = CancelToken.source()

axios.get('http://127.0.0.1:4523/mock/797249/goods/list?keyword=包包', { 
    cancelToken: source.token 
}).catch(function (thrown) { 
    if (axios.isCancel(thrown)) { 
        console.log('Request canceled', thrown.message); 
    } else { 
        // 处理错误 
    } 
})

source.cancel()

此时source如下列状态。

学新通

CancelToken原理基于cancelable promises proposal和XMLHttpRequest.abort,下面是主要源码:

class CancelToken {
  constructor(executor) {
    if (typeof executor !== 'function') {
      throw new TypeError('executor must be a function.');
    }

    let resolvePromise;

    this.promise = new Promise(function promiseExecutor(resolve) {
      resolvePromise = resolve;
    });

    const token = this;

    // ...

    executor(function cancel(message, config, request) {
      if (token.reason) {
        // 已经被取消
        return;
      }

      token.reason = new CanceledError(message, config, request);
      // 对应上面this.promise的resolve
      resolvePromise(token.reason);
    });
  }

  //...
  
  /**
   * Subscribe to the cancel signal
   */

  subscribe(listener) {
    if (this.reason) {
      listener(this.reason);
      return;
    }

    if (this._listeners) {
      this._listeners.push(listener);
    } else {
      this._listeners = [listener];
    }
  }

  /**
   * Returns an object that contains a new `CancelToken` and a function that, when called,
   * cancels the `CancelToken`.
   */
  static source() {
    let cancel;
    const token = new CancelToken(function executor(c) {
      // 对应上面executor回调cancel,执行resolvePromise(token.reason)
      cancel = c;
    });
    return {
      token,
      cancel
    };
  }
}

三、总结

总体来讲,浏览器支持的前端ajax请求,主要有两种XMLHttpRequest和 Request Api,对应的取消请求的方式也有两种:XMLHttpRequest.abort 和 AbortController.abort,记住即可!

这篇好文章是转载于:学新通技术网

  • 版权申明: 本站部分内容来自互联网,仅供学习及演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,请提供相关证据及您的身份证明,我们将在收到邮件后48小时内删除。
  • 本站站名: 学新通技术网
  • 本文地址: /boutique/detail/tanhcaikje
系列文章
更多 icon
同类精品
更多 icon
继续加载