前言

咱们可能会遇到这样的场景:当用户切换页面时,上个页面存在pending中的申请。千里之行;始于足下,如此会造成性能节约,减少服务器压力。本文在于分享基于小程序提供的申请api及 axios 应用中如何勾销不必要的申请。

基于Promise的requestTask封装

// request.jsfunction request(opt) {  const conf = { ... }    let reqTask = null // 保留 request 返回值,并挂载到 promise 上  const promise = new Promise((resolve, reject) => {    reqTask = request({      ...conf,      success(res) {        const { data } = res        // ...        return resolve(data)      },      fail(err) {        return reject(err)      },    })  })  promise.reqTask = reqTask  return promise}export default request
// api.jsimport request from './request'export function fetchData() {  return request({ ... })}
// index.jsimport * as api from '../../api';async fetchData() {  // 个别调用  await api.fetchData().then(response => { ... });},// usageasync fetchOtherData() {  const promise = api.fetchOtherData({ ... });  globalData['reqTask'] = promise.reqTask // 将 requestTask 挂到全局  await promise.then(response => { ... });},
<script>export default {  methods: {    handleClick() {      this.reqTask?.abort() // 勾销申请    },  },}</script>

cancel token的应用

通过传递一个 executor 函数到 CancelToken 的构造函数来创立 cancel token
// file.jsimport axios from 'axios'uploadFile(context, files) {  const CancelToken = axios.CancelToken  for (let i = 0; i < files.length; i++) {    const file = files[i]    const promise = axios      .post('api', data, {        cancelToken: new CancelToken(function executor(c) {          // executor 函数接管一个 cancel 函数作为参数          file.cancel = c          // 全局挂载多个 cancel token          const cancels = []          cancels.push(c)          globalData['cancels'] = cancels        }),      })      .then(response => { ... })      .catch(thrown => {        if (axios.isCancel(thrown)) console.log('Request canceled', thrown.message);        else {          // 处理错误        }      })},
// index.vue<template>  <div>    <div v-for="file in files" :key="file.id">      <!-- cancel the request -->      <div @click="file.cancel" />    </div>  </div></template><script>export default {  methods: {    handleClick() {      // 勾销多个申请      for (let i = 0; i < this.cancels.length; i++) {        this.cancels[i]()      }    },  },}</script>

refs

改良异步封装:解决带返回值的异步调用

axios中文文档