使用http.get node.js的Promise

时间:2016-02-03 16:41:30

标签: javascript node.js promise

我正在做nodechool练习,

  

此问题与上一个问题(HTTP COLLECT)相同   你需要使用http.get()。但是,这次你会   提供了三个URL作为前三个命令行参数。

     

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

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

我正在尝试使用promises =另一个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);
    })

})

但我实际上没有打印数据=我没有通过练习。

我在这里看不到任何错误,但我只是从promises和node开始。错误在哪里?

6 个答案:

答案 0 :(得分:6)

出于教育目的,我最近为使用原生http的{​​{1}}和https模块编写了一个包装器。也就是说,我建议使用一个库,例如request;这使事情更简单,具有单元测试覆盖率,由开源社区维护。此外,我的包装器与响应块进行了一个天真的字符串连接,我不相信这是构建响应主体的最高效方式。

FYI :这需要Node.js 4或更高版本,尽管Node 0.x.x中的方法几乎相同。

Promise

编辑:我刚才意识到你是'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

答案 1 :(得分:2)

我不认为这项练习是用承诺来解决的。我发现了我的旧exercice文件夹,这是我没有承诺或额外库的方式:

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研讨会上有足够的承诺。

答案 2 :(得分:0)

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

首先创建将命中URL并返回promise的函数

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
 });

答案 3 :(得分:0)

这是我完成这个帖子后的解决方案:

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())
       }))  
     })
  });
}

以下是您想要比较笔记的官方解决方案:

 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)  
 }

答案 4 :(得分:0)

使用Promise.all是最有效的解决方案。您也可以使用下面的async / await来解决此问题。

const http = require('http');
const bl = require('bl');

async function httpGet(url) {
    return new Promise((resolve, reject) => {
        http.get(url, response => {
            response.setEncoding('utf8');
            response.pipe(bl((err, data) => {
                if (err) {
                    reject(err);
                }
                resolve(data.toString());
            }));
        });
    });
}

async function main() {

   const data1 = await httpGet(process.argv[2]);
   const data2 = await httpGet(process.argv[3]);
   const data3 = await httpGet(process.argv[4]);
   console.log(data1);
   console.log(data2);
   console.log(data3);
}
main();

答案 5 :(得分:0)

const http = require('http');

const urls = process.argv.slice(2);
let callCount = 0;

const cb =  (res) => {
  res.setEncoding('utf8');

  let rawData = '';
  res.on('data', (chunk) => {
    rawData += chunk.toString();
  });
  res.on('end', () => {
    callCount += 1;
    console.log(rawData);
    if (callCount < urls.length) {
      getData(urls[callCount]);
    }
  });
  res.on('error', (error) => {
    console.log(error);
  });
};


const getData = (url) => {
   http.get(url, cb);
};

getData(urls[callCount]);