Jak uzyskać dane z żądania pobierania HTTP Node.js.

83

Próbuję sprawić, by moja funkcja zwróciła żądanie HTTP get, jednak cokolwiek robię, wydaje się, że gubi się w? Zakresie ?. Jestem zupełnie nowy w Node.js, więc każda pomoc będzie mile widziana

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
źródło

Odpowiedzi:

119

Oczywiście Twoje dzienniki wracają undefined: rejestrujesz się przed wykonaniem żądania. Problem nie dotyczy zakresu, ale asynchroniczności .

http.requestjest asynchroniczna, dlatego jako parametr przyjmuje wywołanie zwrotne. Zrób to, co musisz zrobić w wywołaniu zwrotnym (tym, do którego przechodzisz 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
źródło
10
Zalecałbym umieszczenie fragmentów w tablicy, a następnie użycie na końcu funkcji join (``). Pozwoli to uniknąć problemów, jeśli jest dużo danych
Eric
Jak uzyskać kod odpowiedzi HTTP odpowiedzi (200 lub 404 itd.)? Czy istnieje dokumentacja dotycząca słowa kluczowego „on” (response.on), „data” i „end”? Czy to słowa kluczowe? Wygląda na to, że nic tu nie ma: nodejs.org/api/http.html#http_class_http_serverresponse
Tyler Durden
@TylerDurden statusCodejest właściwością obiektu odpowiedzi. Nie mogłem też znaleźć odpowiedniej dokumentacji dla ServerResponseobiektu, tylko przykłady w dokumentacji metod geti request.
Phoca
1
Ale to sprawia, że ​​kod jest niechlujny! Dlaczego javascript jest zaprojektowany w ten sposób?
Daniel
@Daniel Istnieją teraz udogodnienia do obsługi asynchronicznego modelu zdarzeń: Promises i async / await.
Denys Séguret
16

Krótszy przykład z użyciem http.get:

require('http').get('http://httpbin.org/ip', (res) => {
    res.setEncoding('utf8');
    res.on('data', function (body) {
        console.log(body);
    });
});
Oded Breiner
źródło
Ten przykład jest tak krótki, jak tylko możesz i nadal działa. Zakłada to dobry adres URL i małą odpowiedź. Wolę przykłady http, które dzielą odpowiedź na dane, używają endzdarzenia odpowiedzi i używają errrorzdarzenia żądania .
dturvene
2
Ta odpowiedź jest wyrwana z kontekstu, biorąc pod uwagę zadane pytanie. Poza tym nie nasłuchujesz jawnie, error event co zostanie uruchomione, jeśli połączenie zostanie utracone podczas realizacji żądania lub jeśli podczas transmisji wystąpią jakiekolwiek inne problemy.
rags2riches
10

Prosty przykład roboczy żądania HTTP przy użyciu 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
źródło
1
Dziękuję za udostępnienie !! To była unikalna próbka z danymi zwracanymi bez użycia console.log.
Altieres de Matos
9

z learnyounode:

var http = require('http')  

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

„opcje” to zmienna host / ścieżka

ezchx
źródło
dzięki, wszędzie szukałem prostego przykładu i każdy, który znalazłem, rzucał mi pół tuzina nowych koncepcji. To właśnie pokazało, jak http.get () działa ładnie i prosto. Świetny!
NickW
6

z 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
źródło
3

To jest moje rozwiązanie, choć na pewno możesz użyć wielu modułów, które dają Ci obiekt jako obietnicę lub coś podobnego. W każdym razie brakowało Ci kolejnego oddzwonienia

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

gdzieś indziej

getData(function(data){
// YOUR CODE HERE!!!
})
Ackuser
źródło
to wydaje się nie działać, ponieważ callbackData () nie jest zdefiniowana jako funkcja?
Hugo Koopmans,
1

Myślę, że jest już za późno, aby odpowiedzieć na to pytanie, ale ostatnio napotkałem ten sam problem, moim przypadkiem było wywołanie podzielonego na strony interfejsu API JSON i pobranie wszystkich danych z każdej paginacji i dołączenie ich do pojedynczej tablicy.

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

Jak wspomniał @ackuser, możemy użyć innego modułu, ale w moim przypadku musiałem użyć węzła https. Mając nadzieję, że to pomoże innym.

Vaibhav Rai
źródło
1
Dzięki stary, znalazłem się w takiej samej sytuacji jak ty, to jest do bani, możemy użyć tylko httpsdo wysłania żądania https.
kenshinji