2016-01-08 115 views
0

我想通过node.js中的JS Promises来工作,并且没有获得在不同函数之间传递promise的解决方案。JS承诺在函数之间传递/等待承诺

任务

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

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

index.js中的主逻辑需要等待API函数,直到它可以执行。

问题

  1. 的承诺传球样的作品,但我不知道这是不是一个巧合。返回一个Promise返回makeRequest中的响应是否正确?
  2. 我是否真的需要所有的承诺才能使主逻辑工作,只有等待项目设置后?有一种更简单的方法吗?
  3. 我仍然需要弄清楚,如何最好地处理a)makeRequest和b)getItems函数的错误。对于承诺的最佳做法是什么?传递错误对象?

这里是我想出了现在的代码: 起初我开始做与API请求:

// ./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(); 

一些更多的背景

// 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 request模块,与回调一起工作。由于这些被称为异步,项目从来没有把它放在主逻辑上,我用Promise处理它。

+2

在这里,还有一个在'新的承诺'中包装了现有的承诺[这是一种反模式](http://stackoverflow.com/questions/23803743/what-is-the-explicit-promise-construction-antipattern-and-怎么办,我避免的,它)。你可以从'makeRequest'返回request(options)','getItems'返回makeRequest(api,endpoint)',最后看起来'mainLogic()'应该调用'getItems'而不是其他方法 – CodingIntrigue

回答

4

你在这里失踪两件事情:

  1. ,你可以链的承诺直接与
  2. 的方式承诺,错误处理工作。

您可以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/

+0

谢谢你的回复。这真的帮助我更好地理解Promise。根据你的回答,现在一切正常,但是错误不能从'makeRequest'正确地传递给'API.getItems()。then'函数。我现在就处理这件事。 – Cino