नोड में http.request () पर टाइमआउट कैसे सेट करें?


92

मैं एक HTTP क्लाइंट पर एक समयबाह्य सेट करने का प्रयास कर रहा हूं जो http.request का उपयोग करता है जिसमें कोई भाग्य नहीं है। अब तक मैंने जो किया वह यह है:

var options = { ... }
var req = http.request(options, function(res) {
  // Usual stuff: on(data), on(end), chunks, etc...
}

/* This does not work TOO MUCH... sometimes the socket is not ready (undefined) expecially on rapid sequences of requests */
req.socket.setTimeout(myTimeout);  
req.socket.on('timeout', function() {
  req.abort();
});

req.write('something');
req.end();

कोई संकेत?


1
यह उत्तर मिला (यह भी काम करता है), लेकिन मुझे आश्चर्य है कि अगर http.request () stackoverflow.com/questions/6129240/… के
क्लाउडियो

जवाबों:


26

बस ऊपर दिए गए उत्तर को स्पष्ट करने के लिए :

अब timeoutविकल्प और संबंधित अनुरोध घटना का उपयोग करना संभव है :

// set the desired timeout in options
const options = {
    //...
    timeout: 3000,
};

// create a request
const request = http.request(options, response => {
    // your callback here
});

// use its "timeout" event to abort the request
request.on('timeout', () => {
    request.abort();
});

1
आश्चर्य है कि अगर यह किसी भी तरह से अलग हैsetTimeout(req.abort.bind(req), 3000);
अलेक्जेंडर मिल्स

@AlexanderMills, तब आप संभवत: टाइमआउट को मैन्युअल रूप से खाली करना चाहते हैं, जब अनुरोध ठीक काम करता है।
सर्गेई कोवलेंको

4
ध्यान दें कि यह सख्ती से connectटाइमआउट है, एक बार सॉकेट स्थापित होने के बाद इसका कोई प्रभाव नहीं पड़ता है। तो यह एक सर्वर के साथ मदद नहीं करेगा जो सॉकेट को बहुत अधिक समय तक खुला रखता है (आपको अभी भी अपने स्वयं के सेटटाइमआउट के साथ रोल करने की आवश्यकता होगी)। timeout : A number specifying the socket timeout in milliseconds. This will set the timeout before the socket is connected.
16

यह वही है जो मैं एक त्रिशंकु कनेक्शन प्रयास के लिए देख रहा हूं। एक सर्वर पर एक बंदरगाह तक पहुंचने की कोशिश करते समय त्रिशंकु कनेक्शन एक अच्छा सा हो सकता है जो सुन नहीं रहा है। BTW, API बदल गया है request.destroy( abortपदावनत हो गया है।) इसके अलावा, यह इससे अलग हैsetTimeout
dturvene

91

2019 अपडेट

अब इसे अधिक सुरुचिपूर्ण ढंग से संभालने के लिए विभिन्न तरीके हैं। कृपया इस धागे पर कुछ अन्य उत्तर देखें। टेक तेजी से चलता है, इसलिए उत्तर अक्सर बहुत जल्दी से पुराना हो सकता है। मेरा जवाब अभी भी काम करेगा लेकिन यह विकल्प के रूप में अच्छी तरह से देखने लायक है।

2012 उत्तर

अपने कोड का उपयोग करते हुए, समस्या यह है कि आपने सॉकेट ऑब्जेक्ट पर सामान सेट करने का प्रयास करने से पहले सॉकेट के लिए अनुरोध को सौंपा है। यह सब कुछ ऐसा है:

var options = { ... }
var req = http.request(options, function(res) {
  // Usual stuff: on(data), on(end), chunks, etc...
});

req.on('socket', function (socket) {
    socket.setTimeout(myTimeout);  
    socket.on('timeout', function() {
        req.abort();
    });
});

req.on('error', function(err) {
    if (err.code === "ECONNRESET") {
        console.log("Timeout occurs");
        //specific error treatment
    }
    //other error treatment
});

req.write('something');
req.end();

अनुरोध सॉकेट ऑब्जेक्ट असाइन किए जाने पर 'सॉकेट' ईवेंट को निकाल दिया जाता है।


यह वास्तव में कुल मतलब है। समस्या यह है कि अब मैं इस विशेष मुद्दे (समय गुजरता है ...) का परीक्षण नहीं कर सकता। तो मैं केवल अब के लिए उत्तर को बढ़ा सकता हूं :) धन्यवाद।
क्लाउडियो

कोई चिंता नहीं। ध्यान रखें कि यह केवल नोड के नवीनतम संस्करण पर काम करता है जहाँ तक मुझे पता है। मैंने पिछले संस्करण (5.0.3-पूर्व) पर परीक्षण किया था, मुझे लगता है कि यह सॉकेट घटना को आग नहीं लगाता था।
रोब इवांस

1
इसे संभालने का दूसरा तरीका है कि बोग-स्टैंडर्ड सेटटाइमआउट कॉल का उपयोग करना। आपको सेटटाइमआउट आईडी को अपने पास रखना होगा: var id = setTimeout (...); ताकि आप इसे रद्द कर सकें यदि आप डेटा आदि पर फिर से काम करते हैं। एक अच्छा तरीका यह है कि आप इसे अनुरोध ऑब्जेक्ट में संग्रहीत करें और यदि आपको कुछ डेटा मिलता है तो क्लियर टाइमआउट करें।
रोब इवांस

1
आप याद कर रहे हैं ); req.on के अंत में। चूंकि यह 6 अक्षर नहीं है, इसलिए मैं इसे आपके लिए संपादित नहीं कर सकता।
जेआर स्मिथ

यह काम करता है (धन्यवाद!), लेकिन ध्यान रखें कि प्रतिक्रिया अभी भी आएगी। req.abort()फिलहाल मानक कार्यक्षमता प्रतीत नहीं होती है। इसलिए, socket.onआप एक वैरिएबल को सेट करना चाहते हैं timeout = trueऔर फिर प्रतिक्रिया हैंडलर में उचित रूप से टाइमआउट को संभालना चाहते हैं
जोनाथन बेन

40

इस समय अनुरोध वस्तु पर सीधे ऐसा करने की एक विधि है:

request.setTimeout(timeout, function() {
    request.abort();
});

यह एक शॉर्टकट विधि है जो सॉकेट ईवेंट को बांधता है और फिर टाइमआउट बनाता है।

संदर्भ: Node.js v0.8.8 मैनुअल और प्रलेखन


3
request.setTimeout "सॉकेट पर निष्क्रियता के टाइमआउट मिलीसेकंड के बाद सॉकेट को टाइमआउट करने के लिए सेट करता है।" मुझे लगता है कि यह सवाल गतिविधि की परवाह किए बिना अनुरोध के समय के बारे में है।
इस्टागार्ड

कृपया ध्यान दें कि, नीचे दिए गए उत्तरों में जैसा कि सीधे शामिल सॉकेट का उपयोग करते हैं, req.abort () एक त्रुटि घटना का कारण बनता है, जिसे ('त्रुटि') आदि द्वारा नियंत्रित किया जाना चाहिए
KLoozen

4
request.setTimeout अनुरोध को रद्द नहीं करेगा, हमें टाइमआउट कॉलबैक में मैन्युअल रूप से गर्भपात को कॉल करने की आवश्यकता है।
उध्या

18

रोब इवांस anwser मेरे लिए सही ढंग से काम करता है लेकिन जब मैं request.abort () का उपयोग करता हूं, तो यह एक सॉकेट हैंग एरर को फेंकने के लिए होता है जो अनहेल्दी रहता है।

मुझे अनुरोध ऑब्जेक्ट के लिए एक त्रुटि हैंडलर जोड़ना था:

var options = { ... }
var req = http.request(options, function(res) {
  // Usual stuff: on(data), on(end), chunks, etc...
}

req.on('socket', function (socket) {
    socket.setTimeout(myTimeout);  
    socket.on('timeout', function() {
        req.abort();
    });
}

req.on('error', function(err) {
    if (err.code === "ECONNRESET") {
        console.log("Timeout occurs");
        //specific error treatment
    }
    //other error treatment
});

req.write('something');
req.end();

3
myTimeoutसमारोह कहाँ है ? (संपादित करें: डॉक्स कहते हैं: टाइमआउट इवेंट के लिए बाध्यकारी के रूप में एक ही है नोड्स। http://api/… )
बेन मिरक्रॉफ्ट

नोटिस जो ECONNRESETदोनों मामलों में हो सकता है: क्लाइंट सॉकेट बंद कर देता है और सर्वर कनेक्शन बंद कर देता है। यह निर्धारित करने के लिए कि क्या ग्राहक द्वारा कॉल किया गया है abort()वहाँ स्थानिक abortघटना है
Kirill

8

सरल विधि है।

सेटटाइमआउट का उपयोग करने या सीधे सॉकेट के साथ काम करने के बजाय,
हम ग्राहक उपयोग में 'विकल्प' में 'टाइमआउट' का उपयोग कर सकते हैं

नीचे सर्वर और क्लाइंट दोनों का कोड है, 3 भागों में।

मॉड्यूल और विकल्प भाग:

'use strict';

// Source: https://github.com/nodejs/node/blob/master/test/parallel/test-http-client-timeout-option.js

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

const options = {
    host: '127.0.0.1', // server uses this
    port: 3000, // server uses this

    method: 'GET', // client uses this
    path: '/', // client uses this
    timeout: 2000 // client uses this, timesout in 2 seconds if server does not respond in time
};

सर्वर भाग:

function startServer() {
    console.log('startServer');

    const server = http.createServer();
    server
            .listen(options.port, options.host, function () {
                console.log('Server listening on http://' + options.host + ':' + options.port);
                console.log('');

                // server is listening now
                // so, let's start the client

                startClient();
            });
}

ग्राहक हिस्सा:

function startClient() {
    console.log('startClient');

    const req = http.request(options);

    req.on('close', function () {
        console.log("got closed!");
    });

    req.on('timeout', function () {
        console.log("timeout! " + (options.timeout / 1000) + " seconds expired");

        // Source: https://github.com/nodejs/node/blob/master/test/parallel/test-http-client-timeout-option.js#L27
        req.destroy();
    });

    req.on('error', function (e) {
        // Source: https://github.com/nodejs/node/blob/master/lib/_http_outgoing.js#L248
        if (req.connection.destroyed) {
            console.log("got error, req.destroy() was called!");
            return;
        }

        console.log("got error! ", e);
    });

    // Finish sending the request
    req.end();
}


startServer();

यदि आप उपरोक्त सभी 3 भागों को एक फ़ाइल में रखते हैं, "a.js", और फिर चलाएँ:

node a.js

फिर, उत्पादन होगा:

startServer
Server listening on http://127.0.0.1:3000

startClient
timeout! 2 seconds expired
got closed!
got error, req.destroy() was called!

उम्मीद है की वो मदद करदे।


2

मेरे लिए - यहाँ करने का कम भ्रमित तरीका है socket.setTimeout

var request=require('https').get(
    url
   ,function(response){
        var r='';
        response.on('data',function(chunk){
            r+=chunk;
            });
        response.on('end',function(){
            console.dir(r);            //end up here if everything is good!
            });
        }).on('error',function(e){
            console.dir(e.message);    //end up here if the result returns an error
            });
request.on('error',function(e){
    console.dir(e);                    //end up here if a timeout
    });
request.on('socket',function(socket){
    socket.setTimeout(1000,function(){
        request.abort();                //causes error event ↑
        });
    });

2

यहाँ @douwe के उत्तर पर विस्तृत जानकारी वह है जहाँ आप http अनुरोध पर एक टाइमआउट डालेंगे।

// TYPICAL REQUEST
var req = https.get(http_options, function (res) {                                                                                                             
    var data = '';                                                                                                                                             

    res.on('data', function (chunk) { data += chunk; });                                                                                                                                                                
    res.on('end', function () {
        if (res.statusCode === 200) { /* do stuff with your data */}
        else { /* Do other codes */}
    });
});       
req.on('error', function (err) { /* More serious connection problems. */ }); 

// TIMEOUT PART
req.setTimeout(1000, function() {                                                                                                                              
    console.log("Server connection timeout (after 1 second)");                                                                                                                  
    req.abort();                                                                                                                                               
});

this.abort () भी ठीक है।


1

आपको नीचे दिए गए अनुरोध के संदर्भ को पास करना चाहिए

var options = { ... }
var req = http.request(options, function(res) {
  // Usual stuff: on(data), on(end), chunks, etc...
});

req.setTimeout(60000, function(){
    this.abort();
}).bind(req);
req.write('something');
req.end();

अनुरोध त्रुटि ईवेंट ट्रिगर हो जाएगा

req.on("error", function(e){
       console.log("Request Error : "+JSON.stringify(e));
  });


बाइंड (req) जोड़ने से मेरे लिए कुछ भी नहीं बदला। इस मामले में क्या करता है?
SpiRail

-1

जिज्ञासु, अगर आप net.socketsइसके बजाय सीधे उपयोग करते हैं तो क्या होगा ? यहाँ कुछ नमूना कोड है जिन्हें मैंने परीक्षण के उद्देश्य के लिए रखा है:

var net = require('net');

function HttpRequest(host, port, path, method) {
  return {
    headers: [],
    port: 80,
    path: "/",
    method: "GET",
    socket: null,
    _setDefaultHeaders: function() {

      this.headers.push(this.method + " " + this.path + " HTTP/1.1");
      this.headers.push("Host: " + this.host);
    },
    SetHeaders: function(headers) {
      for (var i = 0; i < headers.length; i++) {
        this.headers.push(headers[i]);
      }
    },
    WriteHeaders: function() {
      if(this.socket) {
        this.socket.write(this.headers.join("\r\n"));
        this.socket.write("\r\n\r\n"); // to signal headers are complete
      }
    },
    MakeRequest: function(data) {
      if(data) {
        this.socket.write(data);
      }

      this.socket.end();
    },
    SetupRequest: function() {
      this.host = host;

      if(path) {
        this.path = path;
      }
      if(port) {
        this.port = port;
      }
      if(method) {
        this.method = method;
      }

      this._setDefaultHeaders();

      this.socket = net.createConnection(this.port, this.host);
    }
  }
};

var request = HttpRequest("www.somesite.com");
request.SetupRequest();

request.socket.setTimeout(30000, function(){
  console.error("Connection timed out.");
});

request.socket.on("data", function(data) {
  console.log(data.toString('utf8'));
});

request.WriteHeaders();
request.MakeRequest();

अगर मैं सॉकेट टाइमआउट का उपयोग करता हूं, और मैं एक के बाद एक दो अनुरोध जारी करता हूं (पहले खत्म होने का इंतजार किए बिना), दूसरे अनुरोध में सॉकेट अपरिभाषित है (कम से कम इस समय मैं टाइमआउट सेट करने की कोशिश करता हूं) .. शायद वहाँ होना चाहिए सॉकेट पर ("तैयार") जैसा कुछ ... मुझे नहीं पता।
क्लाउडियो

@Claudio क्या आप कई अनुरोध किए जाने के लिए अपना कोड अपडेट कर सकते हैं?
onteria_

1
बेशक ... यह थोड़ा लंबा है और मैंने paste2.org का उपयोग किया है अगर यह कोई समस्या नहीं है: paste2.org/p/1448487
क्लाउडियो

@ क्लॉडियो हम्म ठीक है, एक परीक्षण वातावरण की स्थापना और कुछ परीक्षण कोड लिखने के बारे में लेने जा रहा है, इसलिए मेरा उत्तर कल (प्रशांत समय) FYI के रूप में आ सकता है
onteria_

@Claudio वास्तव में एक नज़र ले रहा है कि आपका कोड आपकी त्रुटि के साथ मेल नहीं खाता है। यह कह रहा है कि सेटटाइमआउट को अपरिभाषित मूल्य पर बुलाया जा रहा है, लेकिन जिस तरह से आप इसे कॉल कर रहे हैं वह वैश्विक संस्करण के माध्यम से है, इसलिए ऐसा कोई तरीका नहीं है जो अपरिभाषित हो सकता है, मुझे छोड़कर भ्रमित हो सकता है।
onteria_
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.