简体   繁体   中英

Problem with converting currying form promise chain

We have a utility function that wrappers axios http call; currently it's written in currying form of chained promise as below:

request<T>(request: AxiosRequestConfig, x: number, y: string, z: boolean): Promise<T> {
    return someFunction1(x)
             .then(someFunction2(y))
             .then(sendRequest(z))
             .catch((err) => { // handle error });
}
  function someFunction1(x: number): Promise<string> { }
  function someFunction2(y: string): (s: string) => Promise<AxiosRequestConfig> {}
  function sendRequest(z: boolean): (req: AxiosRequestConfig) => Promise<T> {
     // to other things...
     return axios.request<T>(req)
                 .then(processResponse);
  } 
  function processResponse(): (res: AxiosResponse<T>) => T { 
    // do other things...
    // do something with the res.
  }

To use this, simply call await request(someReq, 1, 'hello', false) . This works but now I want to convert this into async/await form because I want to inject a wrapper on the sendRequest function to add additional logic. I tried to convert them as follows:

 // this now returns a normal promise instead of a function.
 function sendRequest<T>(z: boolean, req: AxiosRequestCofig): Promise<T> {
     // to other things...
     return axios.request<T>(req)
                 .then(processResponse);
 }

 // a function type
 type RealRequestCall<T> = (z: boolean, req: AxiosRequestConfig) => Promise<T>;

 // the wrapper
 async function requestWrapper(z: boolean, req: AxiosRequestConfig, realRequest: RealRequestCall<T>): Promise<T> {

    if (!z) {
      // this is when just forwards the request to the real request call.
      return realRequest(z, req).then(res => res);
    } else {
      const realResponse = await realRequestCall(z, req);
      // do something with the response
     return Promise.resolve(realResponse);
    }
  
 }

 // new request function now uses requestWrapper
function request<T>(request: AxiosRequestConfig, x: number, y: string, z: boolean): Promise<T> {
   return someFunction1(x)
                 .then(someFunction2(y))
                 .then(req => requestWrapper(z, req, sendRequest),
                       (err) => { // handle error });
}

But this does NOT work; I get two axios errors:

  1. Cannot set header after it's sent to client
  2. TypeError: Cannot read property 'processResponse' of undefined\n at sendRequest (/dist/util/http.util.js:102:24)\n at Object. (/dist/util/configProxy.js:20:20)

What did I do wrong in the converting process?

It looks like your approach to wrapping sendRequest won't work, because that function includes the full request response cycle (it waits for the response before returning).

You have a few options:

  1. Completely replace sendRequest wherever it is called, instead of wrapping.
  2. Change the interface of sendRequest so that it doesn't wait for the url call to resolve.
  3. Use axios interceptors

3 is probably your best bet as it's the least invasive, though it has the drawback of being somewhat "magic". If the client code is highly localized or the task is expected to be larger, I'd prefer 1 or 2.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM