JS承诺在函数之间传递/等待promises

时间:2016-01-08 10:37:52

标签: javascript node.js promise ecmascript-6

我正在尝试在node.js中使用JS Promises,并且没有获得在不同函数之间传递promise的解决方案。

任务

对于主逻辑,我需要从REST API获取 items 的json对象。 API处理本身位于api.js文件中。

对API的请求通过request-promise模块进行。我有一个私有的makeRequest函数和公共帮助函数,比如API.getItems()

index.js中的主要逻辑需要等待API函数才能执行。

问题

  1. 承诺传递了一些作品,但我不确定这不仅仅是巧合。返回在makeRequest
  2. 中返回响应的Promise是否正确?
  3. 我是否真的需要所有承诺才能使主逻辑在等待设置项目后才能工作?有更简单的方法吗?
  4. 我仍然需要弄清楚,如何最好地处理来自a makeRequest和b)getItems函数的错误。 Promise的最佳做法是什么?传递错误对象?
  5. 以下是我现在提出的代码:

    // index.js
    
    var API    = require('./lib/api');
    
    var items;
    
    function mainLogic() {
    
      if (items instanceof Error) {
        console.log("No items present. Stopping main logic.");
        return;
      }
    
      // ... do something with items
    }
    
    
    API.getItems().then(function (response) {
      if (response) {
        console.log(response);
        items = response;
        mainLogic();
      }
    }, function (err) {
      console.log(err);
    });
    

    api.js

    // ./lib/api.js
    
    var request = require('request-promise');
    
    // constructor
    var API = function () {
      var api = this;
    
      api.endpoint = "https://api.example.com/v1";
      //...
    };
    
    API.prototype.getItems = function () {
      var api      = this;
      var endpoint = '/items';
    
    
      return new Promise(function (resolve, reject) {
        var request = makeRequest(api, endpoint).then(function (response) {
          if (200 === response.statusCode) {
            resolve(response.body.items);
          }
        }, function (err) {
          reject(false);
        });
      });
    };
    
    function makeRequest(api, endpoint) {
      var url     = api.endpoint + endpoint;
      var options = {
        method: 'GET',
        uri: url,
        body: {},
        headers: {},
        simple: false,
        resolveWithFullResponse: true,
        json: true
      };
    
      return request(options)
        .then(function (response) {
          console.log(response.body);
          return response;
        })
        .catch(function (err) {
          return Error(err);
        });
    }
    
    module.exports = new API();
    

    更多背景资料: 起初我开始使用request模块发出API请求,该模块适用于回调。由于这些被称为异步,所以这些项目从未成为主逻辑,我曾经使用Promises来处理它。

1 个答案:

答案 0 :(得分:4)

你在这里遗漏了两件事:

  1. 你可以直接链接承诺和
  2. 承诺错误处理的方式。
  3. 您可以将makeRequest()中的return语句更改为:

    return request(options);
    

    由于makeRequest()会返回一个承诺,您可以在getItems()中重复使用该承诺,并且您不必明确创建新承诺。 .then()函数已经为您执行此操作:

    return makeRequest(api, endpoint)
        .then(function (response) {
            if (200 === response.statusCode) {
                return response.body.items;
            }
            else {
                // throw an exception or call Promise.reject() with a proper error
            }
        });
    

    如果makeRequest()返回的承诺被拒绝且您没有处理拒绝 - 例如上述代码 - 那么.then()返回的承诺也将被拒绝。您可以将行为与异常进行比较。如果你没有抓到一个,它就会在callstack中冒泡。

    最后,在index.js中,您应该使用getItems(),如下所示:

    API.getItems().then(function (response) {
      // Here you are sure that everything worked. No additional checks required.
      // Whatever you want to do with the response, do it here.
      // Don't assign response to another variable outside of this scope.
      // If processing the response is complex, rather pass it to another 
      // function directly.
    }, function (err) {
      // handle the error
    });
    

    我推荐这篇博文来更好地理解承诺的概念:

    https://blog.domenic.me/youre-missing-the-point-of-promises/