我想将下面的callEndPointWrapper转换为返回Promise而不是回调。
我已经使用以下代码进行了测试,但是在Promise上等待callEndpointWrapper()的请求已超时。
我在下面缺少任何东西吗?
(在调试时,我在等待Promise时看到请求在下面的代码行中超时:
return (function callEndpoint(callback): any {

打回来:

    function callEndPointWrapper(): any {
        return function callEndpoint(callback) {
            try {
                // gRPC call
                client[methodName](req, options, callback);
            }
            catch (err) {
                callback(err);
            }
        };
    }
const result = yield callEndpointWrapper();
// I get the correct result from callback above (both on success or error)


诺言:

function callEndPointWrapper(): Promise<any> {
  return new Promise( (resolve, reject) => {
    return (function callEndpoint(callback): any {
      try {
        // gRPC call
        resolve(client[methodName](req, options, callback));
      } catch (err) {
        reject(callback(err));
      }
    });
  });
const result = await callEndpointWrapper();
// Above request times out.

最佳答案

callEndPointWrapper的期望结果似乎是一个函数(callEndPoint),它执行一些异步工作,您可以进一步调用该异步工作来执行某些操作。

在回调方法中,您正在生成此callEndPoint函数。

----> callEndPointWrapper返回执行异步工作的callEndPoint

另一方面,在基于诺言的方法中,您尝试产生callEndPoint的结果,而不是返回callEndPoint本身。实际上,在callEndPoint构造函数中永远不会调用Promise

----> callEndPointWrapper返回一个永不解决的承诺,并在内部创建callEndPoint函数,该函数不执行任何操作,因为它从未被调用。

重要的是要注意,对callEndPointWrapper的单个调用不是异步的。实际的异步部分(假设client方法是异步的)发生在callEndpoint中,因此基于回调的方法的异步调用将类似于:

callEndPointWrapper()(
  function callback(responseFromEndpoint) {
    // ...
  }
)

// or something like
let caller = callEndPointWrapper();
caller(function callback(responseFromEndpoint) {
    // ...
});


因此,基于诺言的方法也将需要两个调用:

await callEndPointWrapper()(); // call a wrapper which returns a function which returns a promise


以下是功能上等效(就产生的结果而言)的基于promise的回调代码:

function callEndPointWrapper(): any {
    return function callEndpoint() {
      return new Promise((resolve, reject) => {
        try {
          client[methodName](req, options, (err, result) => {
            if (err) return reject(err);
            resolve(result);
          });
        } catch (err) {
          // Note: this rejection will only happen on any sync errors
          // with the above code, such as trying to invoke a non-existing
          // method on the client. This type of error is a programmer error
          // rather than an operational error in the system so you should
          // consider if such errors should even by caught by your code.
          reject(err);
        }
      });
   };
}


但是,这引出了一个问题,即如果您没有传递任何配置选项以使callEndpoint函数的结尾可用,那么完全具有包装器功能有什么意义呢?

根据您的示例用法,您只需要callEndpoint方法。



想到您可能正在使用类似co之类的东西,它允许您使用yield函数(thunk)并使用回调在内部调用它们。

所以当你这样做

yield callEndpointWrapper()


你实际上是在打电话

yield function callEndpoint(callback) {
  // ...
}


然后co为您做一些魔术。

这是deprecated by co的模式,总体上不建议使用。更不用说这是非常令人困惑的(和丑陋的恕我直言)行为,需要了解特定的库。

要将诺言与co一起使用,则不需要包装函数。只是yieldawait调用callEndPoint的结果(与我上面的promise示例中的结果相同),这将是一个promise。

yield callEndPoint()
// or
await callEndPoint()

10-04 14:22