如何包装异步包函数?

时间:2017-01-30 15:27:58

标签: javascript node.js asynchronous promise control-flow

我使用热门节点库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。

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

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

  doMoreStuffWithResponse(res);
}

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

我也完全敞开心扉,认为这一切都是错误的。在这种情况下,我会很感激一些重定向。

感谢您的时间。

2 个答案:

答案 0 :(得分:3)

了解Promise 是什么。它是,你可以这样对待它。为了“读取”该值,您将函数传递给Promise的then方法。您不需要myBigFunction。在Promise结算后你想要运行的任何东西都需要传递给then

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

现在,虽然我经常这样做,但我并不特别关心这种方式。我更喜欢使用接受承诺的函数并调用他们的then方法:

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

请注意,它会返回已完成任务的Promise。但我更喜欢的是ES6单线:

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

现在您可以包装任意函数以将Promises作为输入并将它们作为输出返回。如果Promises是monad,那么这将是他们的bind函数。使其与任意arity的功能无缝地工作留给读者练习。

答案 1 :(得分:1)

您总是希望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);
});
相关问题