javascript - 将回调转换为 Promise

标签 javascript node.js callback promise

我想将下面的 callEndPointWrapper 转换为返回 Promise 而不是回调。 我已经使用以下代码进行了测试,但是等待 callEndpointWrapper() 的 Promise 请求超时。 我错过了下面的任何东西吗? (在调试时,我看到请求在等待 Promise 时在下面的代码行超时: 返回(函数调用端点(回调):任何{

回调:

    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)

promise :

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

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

----> callEndPointWrapper 返回一个永远不会解析的 promise ,并在内部创建一个什么都不做的 callEndPoint 函数,因为它从未被调用。

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

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

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

由此可见,基于 promise 的方法也需要两次调用:

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 函数 (thunks) 并通过回调在内部调用它们。

所以当你这样做的时候

yield callEndpointWrapper()

你实际上是在打电话

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

然后 co 在幕后为您施展魔法。

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

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

yield callEndPoint()
// or
await callEndPoint()

关于javascript - 将回调转换为 Promise,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47226849/

相关文章:

javascript - 除了 alert 和 document.write 之外打印输出的方法

node.js - 使用带有 userID 的 Rest API 拉取用户数据

linux - 服务器端node.js请求无法连接到主机

java - Android 5.0 Lollipop 中的 mediaPlayer,我无法播放,来自 url 的长声音。在 Android 5.0 到来之前我从未遇到过任何问题

javascript - 单个标记卡在 Fusion Tables 图层中的多边形下方

javascript - 使用 Angular 获取数据 API 调用时出错

c - ansi c 全局可访问回调

javascript - 如何传递可变数量的参数以及回调函数?

javascript - 为什么 String#match() 结果不包含捕获的值?

node.js - 在 Node 中进行集成测试后清理 mongodb