Cómo obtener datos de una solicitud http get de Node.js

82

Estoy tratando de que mi función devuelva la solicitud http get, sin embargo, cualquier cosa que haga parece perderse en el? Alcance ?. Soy nuevo en Node.js, por lo que cualquier ayuda sería apreciada

function getData(){
  var http = require('http');
  var str = '';

  var options = {
        host: 'www.random.org',
        path: '/integers/?num=1&min=1&max=10&col=1&base=10&format=plain&rnd=new'
  };

  callback = function(response) {

        response.on('data', function (chunk) {
              str += chunk;
        });

        response.on('end', function () {
              console.log(str);
        });

        //return str;
  }

  var req = http.request(options, callback).end();

  // These just return undefined and empty
  console.log(req.data);
  console.log(str);
}
Daryl Rodrigo
fuente

Respuestas:

118

Por supuesto, sus registros regresan undefined: inicia sesión antes de que se realice la solicitud. El problema no es el alcance sino la asincronicidad .

http.requestes asincrónico, por eso toma una devolución de llamada como parámetro. Haz lo que tengas que hacer en la devolución de llamada (a la que pasas response.end):

callback = function(response) {

  response.on('data', function (chunk) {
    str += chunk;
  });

  response.on('end', function () {
    console.log(req.data);
    console.log(str);
    // your code here if you want to use the results !
  });
}

var req = http.request(options, callback).end();
Denys Séguret
fuente
10
Recomendaría empujar los trozos en una matriz y luego usar join ('') al final. Eso evitará problemas si hay muchos datos
Eric
¿Cómo obtengo el código de respuesta HTTP de la respuesta (200 o 404, etc.)? ¿Existe alguna documentación sobre la palabra clave 'on' (response.on), 'data' y 'end'? ¿Son estas palabras clave? Parece que no hay nada aquí: nodejs.org/api/http.html#http_class_http_serverresponse
Tyler Durden
@TylerDurden statusCodees una propiedad del objeto de respuesta. Tampoco pude encontrar la documentación adecuada para el ServerResponseobjeto, solo ejemplos en los documentos para los métodos gety request.
Phoca
1
¡Pero esto hace que el código sea complicado! ¿Por qué JavaScript está diseñado así?
Daniel
@Daniel Ahora hay facilidades para manejar el modelo de evento asincrónico: Promises y async / await.
Denys Séguret
15

Ejemplo más corto usando http.get:

require('http').get('http://httpbin.org/ip', (res) => {
    res.setEncoding('utf8');
    res.on('data', function (body) {
        console.log(body);
    });
});
Oded Breiner
fuente
Este ejemplo es lo más breve posible y aún se ejecuta. Esto supone una buena URL y una pequeña respuesta. Prefiero los ejemplos http que fragmentan la respuesta de datos, usan el endevento de respuesta y usan el errrorevento de solicitud .
dturvene
2
Esta respuesta está fuera de contexto dada la pregunta formulada. Además de eso, no está escuchando explícitamente lo error event que se activará si la conexión se pierde mientras la solicitud está en curso o si ocurre algún otro problema durante la transmisión.
rags2riches
9

de learnyounode:

var http = require('http')  

http.get(options, function (response) {  
  response.setEncoding('utf8')  
  response.on('data', console.log)  
  response.on('error', console.error)  
})

'opciones' es la variable de host / ruta

ezchx
fuente
gracias, he estado buscando por todas partes un ejemplo simple y cada uno que encontré me arrojó media docena de conceptos nuevos. Esto acaba de explicar cómo funciona http.get () de forma agradable y sencilla. ¡Excelente!
NickW
9

Ejemplo de trabajo simple de solicitud Http usando node.

const http = require('https')

httprequest().then((data) => {
        const response = {
            statusCode: 200,
            body: JSON.stringify(data),
        };
    return response;
});
function httprequest() {
     return new Promise((resolve, reject) => {
        const options = {
            host: 'jsonplaceholder.typicode.com',
            path: '/todos',
            port: 443,
            method: 'GET'
        };
        const req = http.request(options, (res) => {
          if (res.statusCode < 200 || res.statusCode >= 300) {
                return reject(new Error('statusCode=' + res.statusCode));
            }
            var body = [];
            res.on('data', function(chunk) {
                body.push(chunk);
            });
            res.on('end', function() {
                try {
                    body = JSON.parse(Buffer.concat(body).toString());
                } catch(e) {
                    reject(e);
                }
                resolve(body);
            });
        });
        req.on('error', (e) => {
          reject(e.message);
        });
        // send the request
       req.end();
    });
}
smsivaprakaash
fuente
1
Gracias por compartir !! Esta fue la muestra única con datos devueltos sin usar console.log.
Altieres de Matos
6

de learnyounode:

var http = require('http')
var bl = require('bl')

http.get(process.argv[2], function (response) {
    response.pipe(bl(function (err, data) {
        if (err)
            return console.error(err)
        data = data.toString()
        console.log(data)
    }))
})
Elise Chant
fuente
3

Esta es mi solución, aunque seguro que puedes usar muchos módulos que te dan el objeto como promesa o similar. De todos modos, te faltaba otra devolución de llamada

function getData(callbackData){
  var http = require('http');
  var str = '';

  var options = {
        host: 'www.random.org',
        path: '/integers/?num=1&min=1&max=10&col=1&base=10&format=plain&rnd=new'
  };

  callback = function(response) {

        response.on('data', function (chunk) {
              str += chunk;
        });

        response.on('end', function () {
              console.log(str);
          callbackData(str);
        });

        //return str;
  }

  var req = http.request(options, callback).end();

  // These just return undefined and empty
  console.log(req.data);
  console.log(str);
}

en algún otro lugar

getData(function(data){
// YOUR CODE HERE!!!
})
ackuser
fuente
esto parece no funcionar ya que callbackData () no está definido como una función?
Hugo Koopmans
1

Creo que es demasiado tarde para responder a esta pregunta, pero recientemente enfrenté el mismo problema, mi caso de uso fue llamar a la API JSON paginada y obtener todos los datos de cada paginación y agregarlos a una sola matriz.

const https = require('https');
const apiUrl = "https://example.com/api/movies/search/?Title=";
let finaldata = [];
let someCallBack = function(data){
  finaldata.push(...data);
  console.log(finaldata);
};
const getData = function (substr, pageNo=1, someCallBack) {

  let actualUrl = apiUrl + `${substr}&page=${pageNo}`;
  let mydata = []
  https.get(actualUrl, (resp) => {
    let data = '';
    resp.on('data', (chunk) => {
        data += chunk;
    });
    resp.on('end', async () => {
        if (JSON.parse(data).total_pages!==null){
          pageNo+=1;
          somCallBack(JSON.parse(data).data);
          await getData(substr, pageNo, someCallBack);
        }
    });
  }).on("error", (err) => {
      console.log("Error: " + err.message);
  });
}

getData("spiderman", pageNo=1, someCallBack);

Como mencionó @ackuser, podemos usar otro módulo, pero en mi caso de uso tuve que usar el nodo https. Esperando que esto ayude a otros.

Vaibhav Rai
fuente
1
Gracias amigo, me encontré con la misma situación que tú, apesta, solo podemos usar el httpspara emitir una solicitud https.
kenshinji