如何包装异步包函数?

How to wrap an async package function?

我正在使用流行的节点库 got 向 JSON API.

发出简单的 GET 请求

我有一个抽象请求的函数,如下所示:

function performRequest(url) {
  got(url, {
    json: true
  }).then(function (response) {
    return formatResponse(response.body);
  }).catch(function (error) {
    console.log(error.response.body);
  });
}

formatResponse 是一个简单的同步方法,它从 API.

修改 JSON returned

我希望能够从另一个函数调用 performRequest,然后使用 return 值(一旦解析)。目前,由于 performRequest 未被识别为异步方法,我的代码正在调用它然后立即继续。

function myBigFunction() {
  var url = composeUrl();
  var res = performRequest(url);

  doMoreStuffWithResponse(res);
}

我知道我需要使用 Promise,但是,我总是不清楚如何将 Promise 与已经在使用 Promise 的内置库函数结合使用(例如在这种情况下)。

我也完全接受我做这一切都是错误的可能性。在那种情况下,我将不胜感激。

感谢您的宝贵时间。

了解什么是 Promise 。它是一个,你可以这样对待它。为了 "read" 该值,您将一个函数传递给 Promise 的 then 方法。你不需要 myBigFunction。在 Promise 解析后你想要 运行 的任何东西只需要传递给 then:

var req = performRequest(composeURL());
req.then(doStuffWithResponse);

现在,我并不特别喜欢这种方式,尽管我经常这样做。我更喜欢 take 承诺并调用他们的 then 方法的函数:

var takesAPromise = function(p) {
  return p.then(/* does stuff */);
};

请注意,它 return 是已完成任务的 Promise。但我更喜欢这个 ES6 one-liner:

let wrap = f => p => p.then(val => f.call(null, val));

现在您可以包装任意函数以将 Promises 作为输入并 return 它们作为输出。如果 Promises 是一个 monad,这将是它们的 bind 函数。让它与任意数量的函数无缝工作留作 reader.

的练习。

你总是想要return你的函数的承诺:

function performRequest(url) {
  return got(url, {
//^^^^^^
    json: true
  }).then(function(response) {
    return formatResponse(response.body);
  }, function(error) {
    throw new Error(error.response.body);
  });
}

有了这个,您可以使用另一个 then:

在您的大函数中等待结果
function myBigFunction() {
  var url = composeUrl();
  var promise = performRequest(url);
  return promise.then(function(res) {
    return doMoreStuffWithResponse(res);
  });
}

或者简而言之

function myBigFunction() {
  return performRequest(composeUrl()).then(doMoreStuffWithResponse);
}

这样你就可以这样称呼它

myBigFunction().catch(function(error) {
  console.log(error.message);
});