wx.request 经 Promise 封装后,如何拿到requestTask
发布于 4 年前 作者 ogu 4944 次浏览 来自 问答


大家会用 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 回复

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" });
    }
  }
}
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();
 })

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。

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

回到顶部