收藏
回答

wx.request 经 Promise 封装后,如何拿到requestTask


大家会用 promise 将 wx.request 包装一层。但经过这么一层包装后,就拿到不到 requestTask,从而调用不了 abort 方法。大家都是如何解决的? 代码来自:https://www.kancloud.cn/xiaoyulive/wechat/526990

class Request {
  constructor (parms) {
    this.withBaseURL = parms.withBaseURL
    this.baseURL = parms.baseURL
  }
  get (url, data) {
    return this.request('GET', url, data)
  }
  post (url, data) {
    return this.request('POST', url, data)
  }
  put (url, data) {
    return this.request('PUT', url, data)
  }
  request (method, url, data) {
    const vm = this
    return new Promise((resolve, reject) => {
      wx.request({
        url: vm.withBaseURL ? vm.baseURL + url : url,
        data,
        method,
        success (res) {
          resolve(res)
        },
        fail () {
          reject({
            msg: '请求失败',
            url: vm.withBaseURL ? vm.baseURL + url : url,
            method,
            data
          })
        }
      })
    })
  }
}
 
const request = new Request({
  baseURL: 'http://test',
  withBaseURL: true
})
 
module.exports = request



回答关注问题邀请回答
收藏

3 个回答

  • 晓初
    晓初
    2019-12-02

    function r() {

      let task = {}
      const promise = new Promise((resolve) => {
          let timer
          task.abort = function () {
            clearTimeout(timer)
          }
     
          timer = setTimeout(() => {
            resolve()
          }, 1000)
        })
     
     
      promise.task = task
      return promise
    }
     
     
    function a() {
      return r()
    }
     
    var promise = a()
     
    promise.then(res => {
      console.log(1)
    })
     
    promise.task.abort()
     
     
    a().then(res => {
      console.log(2)
    })

    demo实现思路,挂载在返回的promise上,但会有问题,你可以看到在调用的时候需要手动声明一个promise变量,不能直接a().then() 因为then返回的是一个新的Promise,上面没有挂载的task。

    今天遇到了这个问题,在不影响从前的代码的情况下想出来的。更好的思路暂时没有。这里就抛砖引玉了

    2019-12-02
    有用 2
    回复
  • DL
    DL
    2019-12-10
    class Request {
    constructor(parms) {
    this.withBaseURL = parms.withBaseURL;
    this.baseURL = parms.baseURL;
    this.requestTask = null;
    }

    get(url, data) {
    return this.request('GET', url, data);
    }

    post(url, data) {
    return this.request('POST', url, data);
    }

    put(url, data) {
    return this.request('PUT', url, data);
    }

    request(method, url, data) {
    const vm = this;
    return new Promise((resolve, reject) => {
    this.requestTask = wx.request({
    url: vm.withBaseURL ? vm.baseURL + url : url,
    data,
    method,
    success(res) {
    resolve(res);
    },
    fail() {
    reject({
    msg: '求失',
    url: vm.withBaseURL ? vm.baseURL + url : url,
    method,
    data
    });
    }
    });
    });
    }

    abort() {
    if (this.requestTask) {
    this.requestTask.abort();
    }
    }
    }

    const request = new Request({
    baseURL: 'http://test',
    withBaseURL: true
    });

    module.exports = request;

    --------

    调用:

    request.get(xxx, xxx).then((res) => {
      request.abort();
     })

    2019-12-10
    有用 1
    回复 2
    • ice breaker
      ice breaker
      2019-12-16
      这个封装有一些问题,导出是单例意味着api共享一个Request实例,出现并发时,requestTask 会被多次覆盖,正常使用必须要new多个Request实例,不然会导致abort不知道取消哪一个task.另外一个问题则是没有考虑小程序请求的并发量,需要接入并发队列来管理,这时候task的处理方式。
      2019-12-16
      4
      回复
    • 深蓝
      深蓝
      03-11
      直接把Request类导出就好了,用的时候就去new一个新的对象,自己管理自己的task。
      03-11
      回复
  • 小黑
    小黑
    2019-12-10

    ts源码:


     
    export namespace Hz.Http {
     
      const ES6Promise = require('es6-promise');
     
      export interface DatasObject {
        [data: string]: number | string | string[] | undefined;
      }
     
      export interface HeadersObject {
        [header: string]: number | string | string[] | undefined;
      }
     
      export interface RequestParams {
        url: string;
        method?: string;
        dataType?: string;
        data?: string | DatasObject | ArrayBuffer;
        header?: HeadersObject;
        responseType?: string;
      }
     
      export class HttpError extends Error {
     
        public statusCode: number;
        public header: HeadersObject;
        public body: string | object | ArrayBuffer;
     
        constructor(statusCode: number, header: HeadersObject, body: string | object | ArrayBuffer) {
          super(`response status code: ${statusCode}`);
          this.statusCode = statusCode;
          this.header = header;
          this.body = body;
        }
      }
     
      export class ResponsePromise<T> extends ES6Promise<T> {
     
        public statusCode: number;
        public header: HeadersObject;
        public body: string | object | ArrayBuffer;
     
        public requestTask: WechatMiniprogram.RequestTask;
     
        constructor(executor: (resolve: (value?: T | PromiseLike<T>) => void, reject: (reason?: any) => void) => void) {
          super(executor);
        }
     
        public onHeadersReceived(callback: WechatMiniprogram.RequestTaskOnHeadersReceivedCallback) {
          this.requestTask.onHeadersReceived(callback);
        }
     
        public offHeadersReceived(callback: WechatMiniprogram.RequestTaskOffHeadersReceivedCallback) {
          this.requestTask.offHeadersReceived(callback);
        }
     
        public abort(): void {
          this.requestTask.abort();
        }
      }
     
      export class Request {
     
        public static ExecAsync<T>(pars: RequestParams): ResponsePromise<T> {
     
          var requestTask: WechatMiniprogram.RequestTask;
     
          var p = new ResponsePromise<T>((resolve, reject) => {
     
            try {
              requestTask = wx.request({
                url: pars.url,
                data: pars.data,
                header: pars.header,
                method: pars.method,
                dataType: pars.dataType,
                responseType: pars.responseType,
                success(res) {
     
                  if (res.statusCode >= 200 && res.statusCode < 300) {
     
                    p.statusCode = res.statusCode;
                    p.header = res.header;
                    p.body = res.data;
     
                    resolve(res.data);
                  }
                  else {
                    reject(new HttpError(res.statusCode, res.header, res.data));
                  }
     
                },
                fail(err) {
                  reject(new Error(err.errMsg));
                }
              });
            }
            catch (e) {
              reject(e);
            }
     
          });
     
          p.requestTask = requestTask;
          return p;
        }
     
        public static getAsync<T>(url: string, data?: string | DatasObject | ArrayBuffer, header?: HeadersObject): ResponsePromise<T> {
          return Request.ExecAsync<T>({ url: url, data: data, header: header, method: "GET" });
        }
     
        public static postAsync<T>(url: string, data?: string | DatasObject | ArrayBuffer, header?: HeadersObject): ResponsePromise<T> {
          return Request.ExecAsync<T>({ url: url, data: data, header: header, method: "POST" });
        }
     
        public static deleteAsync<T>(url: string, data?: string | DatasObject | ArrayBuffer, header?: HeadersObject): ResponsePromise<T> {
          return Request.ExecAsync<T>({ url: url, data: data, header: header, method: "DELETE" });
        }
      }
    }


    2019-12-10
    有用
    回复 3
    • 小黑
      小黑
      2019-12-10
      2019-12-10
      回复
    • 小黑
      小黑
      2019-12-10
      小补丁,修复 .then().catch() 返回对象丢失信息问题。
      2019-12-10
      回复
    • 伟
      01-17
      大佬,我试了不行啊,不加await 调用得到的是Promise {}
      01-17
      回复
登录 后发表内容