用http.get node.js承诺

我在做nodechool练习

这个问题和前面的问题(HTTP COLLECT)是一样的,你需要使用http.get()。 但是,这次您将获得三个URL作为前三个命令行参数。

您必须收集每个URL提供给您的完整内容并将其打印到控制台(stdout)。 您不需要打印出长度,只需将数据打印为string; 每个URL一行。 问题在于,你必须按照与作为命令行参数提供给你的URL相同的顺序打印出来。

换句话说,我要注册3个http.get请求,并按顺序打印它接收到的数据。

我正在尝试与承诺=另一个请求不会被称为直到第一个没有结束。

我的代码看起来像这样

var http=require("http"); var collect=[]; var dat=[]; for( var i = 2 ; i < process.argv.length;i++){ collect.push(process.argv[i]); } function chainIt(array,callback){ return array.reduce(function(promise,item){ return promise.then(function(){ return callback(item) }) },Promise.resolve()) } function getIt(item){ return http.get(item,function(response){ response.on("data",function(data){ dat.push(data); }) }) } chainIt(collett,function(item){ return getIt(item) }) }).then(function(){ collect.forEach(function(x){ console.log(x); }) }) 

但是我实际上没有打印数据=我没有做这个练习。

我没有看到任何bug,但我只是从承诺和节点开始。 错误在哪里?

为了教育目的,我最近为使用原生Promisehttphttps模块编写了一个包装器。 也就是说,我build议使用一个库,这样的request ; 这使得事情变得更简单,具有unit testing的覆盖范围,正如开源社区所维护的那样。 另外,我的包装做了一个天真的string连接与响应块,我不相信是构build响应主体的最高性能的方式。

仅供参考 :这需要Node.js 4或更高版本,虽然方法在Node 0.xx中几乎相同

 'use strict'; const http = require('http'); const url = require('url'); module.exports = { get(url) { return this._makeRequest('GET', url); }, _makeRequest(method, urlString, options) { // create a new Promise return new Promise((resolve, reject) => { /* Node's URL library allows us to create a * URL object from our request string, so we can build * our request for http.get */ const parsedUrl = url.parse(urlString); const requestOptions = this._createOptions(method, parsedUrl); const request = http.get(requestOptions, res => this._onResponse(res, resolve, reject)); /* if there's an error, then reject the Promise * (can be handled with Promise.prototype.catch) */ request.on('error', reject); request.end(); }); }, // the options that are required by http.get _createOptions(method, url) { return requestOptions = { hostname: url.hostname, path: url.path, port: url.port, method }; }, /* once http.get returns a response, build it and * resolve or reject the Promise */ _onResponse(response, resolve, reject) { const hasResponseFailed = response.status >= 400; var responseBody = ''; if (hasResponseFailed) { reject(`Request to ${response.url} failed with HTTP ${response.status}`); } /* the response stream's (an instance of Stream) current data. See: * https://nodejs.org/api/stream.html#stream_event_data */ response.on('data', chunk => responseBody += chunk.toString()); // once all the data has been read, resolve the Promise response.on('end', () => resolve(responseBody)); } }; 

编辑:我只是意识到你是Promise的新来的。 这是一个如何使用这个包装器的例子:

 'use strict'; const httpService = require('./httpService'); // the above wrapper // get one URL httpService.get('https://ron-swanson-quotes.herokuapp.com/v2/quotes').then(function gotData(data) { console.log(data); }); // get multiple URLs const urls = [ 'https://ron-swanson-quotes.herokuapp.com/v2/quotes', 'http://api.icndb.com/jokes/random' ]; /* map the URLs to Promises. This will actually start the * requests, but Promise.prototype.then is always called, * even if the operation has resolved */ const promises = urls.map(url => httpService.get(url)); Promise.all(promises).then(function gotData(responses) { /* responses is an array containing the result of each * Promise. This is ordered by the order of the URLs in the * urls array */ const swansonQuote = responses[0]; const chuckNorrisQuote = responses[1]; console.log(swansonQuote); console.log(chuckNorrisQuote); }); 

其中一种方法是使用'Q'库。

首先创build会打URL并返回承诺的函数

 var Q = require('q); function getIt(item){ return http.get(item,function(response){ return Q.resolve(response); // Return response OR return Q.resolve(error); // Return error }) }) } var urls = ['url1','url2','url3']; // list of urls Q.spread(urls.map(getIt)) .then(function(res1,res2,res3){ // res1 is response for url1 and on //Once all calls are finished you will get results here }); 

我不认为这个练习是用承诺来解决的。 我发现我的旧的行使文件夹,这是我没有承诺或额外的图书馆:

 var http = require('http'); var urls = process.argv.slice(2); // counts the number of requests done var done = 0; // stores the requests result var result = []; // this will be called by each http.get and they will provide their index function callback(index, data) { result[index] = data; done++; // all requests are done, log everything if (done == urls.length) { result.forEach(console.log); } } function processUrl(url, index) { var finalData = ''; http.get(url, function(response) { response.setEncoding('utf8'); response.on('data', function(data) { finalData += data; }); response.on('error', console.error); response.on('end', function() { // console.log(finalData); callback(index, finalData); }) }); } urls.forEach(processUrl); 

不要担心,在promise-it-wont-hurt工作坊里,你将有足够的承诺来玩。

这是我通过这个线程后的解决scheme:

 var http = require('http'); var bl = require('bl') promises = [ promiseLoad(process.argv[2]), promiseLoad(process.argv[3]), promiseLoad(process.argv[4]) ]; Promise.all(promises).then(function(res) { for(i=0; i<promises.length; i++) { console.log(res[i]); } }); function promiseLoad(url) { var body = ''; return new Promise(function(resolve, reject) { http.get(url, function (response) { response.setEncoding('utf8'); response.pipe(bl(function (err, data) { resolve(data.toString()) })) }) }); } 

如果你想比较笔记,这是官方的解决scheme:

  var http = require('http') var bl = require('bl') var results = [] var count = 0 function printResults () { for (var i = 0; i < 3; i++) { console.log(results[i]) } } function httpGet (index) { http.get(process.argv[2 + index], function (response) { response.pipe(bl(function (err, data) { if (err) { return console.error(err) } results[index] = data.toString() count++ if (count === 3) { printResults() } })) }) } for (var i = 0; i < 3; i++) { httpGet(i) }