নোডের একটি http.request () এ কীভাবে একটি টাইমআউট সেট করবেন?


94

আমি কোনও 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();

কোন ইঙ্গিত?


4
এই উত্তরটি পাওয়া (এটা খুব কাজ করে) কিন্তু আমি ভাবছি যদি সেখানে http.request জন্য ভিন্ন কিছু আছে () stackoverflow.com/questions/6129240/...
ক্লডিও

উত্তর:


28

কেবল উপরের উত্তরটি পরিষ্কার করতে :

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

4
ভাবছি যদি এই মাত্র ছাড়া ভিন্নsetTimeout(req.abort.bind(req), 3000);
আলেকজান্ডার মিলস

@ আলেকজান্ডারমিলস, অনুরোধটি ঠিকঠাক কাজ করার পরে আপনি সম্ভবত সময়সীমাটি ম্যানুয়ালি সাফ করতে চান।
সের্গেই কোভালেনকো

4
দ্রষ্টব্য যে এটি কঠোরভাবে connectসময়সীমা, একবার সকেটটি প্রতিষ্ঠিত হওয়ার পরে এর কোনও প্রভাব নেই। সুতরাং এটি এমন কোনও সার্ভারে সহায়তা করবে না যা সকেটকে খুব বেশি সময়ের জন্য উন্মুক্ত রাখে (আপনাকে এখনও সেটটাইমআউট দিয়ে নিজের রোল করতে হবে)। timeout : A number specifying the socket timeout in milliseconds. This will set the timeout before the socket is connected.
আপক্রিক

এটি হ্যাং সংযোগের প্রচেষ্টাতে আমি যা খুঁজছি। যে সার্ভারটি শুনতে পাচ্ছে না এমন কোনও পোর্ট অ্যাক্সেস করার চেষ্টা করার সময় হাং সংযোগগুলি খুব ভাল ঘটতে পারে। BTW, API- এ পরিবর্তিত হয়েছে request.destroy( abort। অবচিত) এ ছাড়া, এই থেকে ভিন্নsetTimeout
dturvene

92

2019 আপডেট

এখন আরও মার্জিতভাবে এটি পরিচালনা করার বিভিন্ন উপায় রয়েছে। দয়া করে এই থ্রেডে আরও কিছু উত্তর দেখুন। প্রযুক্তি দ্রুত চলে আসে তাই উত্তরগুলি প্রায়শই বেশিরভাগ ক্ষেত্রেই পুরানো হয়ে যায়। আমার উত্তরটি এখনও কার্যকর হবে তবে বিকল্পগুলির দিকে নজর দেওয়াও মূল্যবান।

2012 উত্তর

আপনার কোড ব্যবহার করে, সমস্যাটি হ'ল আপনি সকেটের অবজেক্টে স্টাফ সেট করার চেষ্টা করার আগে অনুরোধের জন্য সকেট বরাদ্দের অপেক্ষা করেন নি। এটি সমস্ত async তাই:

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-প্রাক) আমি মনে করি এবং এটি সকেট ইভেন্টটিকে আগুন দেয় না।
রব ইভান্স

4
এটি পরিচালনা করার অন্য উপায়টি হ'ল বগ-স্ট্যান্ডার্ড সেটটাইমআউট কল ব্যবহার করা। আপনাকে সেটটাইমআউট আইডিটি ধরে রাখতে হবে: var id = setTimeout (...); যাতে আপনি এটিতে কোনও ডেটা গ্রহণ করেন তবে আপনি এটি বাতিল করতে পারেন A একটি ভাল উপায় হ'ল এটি অনুরোধের অবজেক্টে নিজেই সংরক্ষণ করা হয় তবে কিছু তথ্য পেলে ক্লিয়ারটাইমআউট করুন।
রব ইভান্স

4
আপনি মিস করছেন); rek.on শেষে। যেহেতু এটি 6 টি অক্ষর নয়, আমি আপনার জন্য এটি সম্পাদনা করতে পারি না।
জেআর স্মিথ

এটি কার্যকর (ধন্যবাদ!), তবে মনে রাখবেন যে প্রতিক্রিয়াটি এখনও অবশেষে আসবে। req.abort()এই মুহুর্তে মানক কার্যকারিতা বলে মনে হচ্ছে না। অতএব, আপনার মধ্যে socket.onমত একটি পরিবর্তনশীল সেট করতে timeout = trueএবং তারপরে প্রতিক্রিয়া হ্যান্ডলারের যথাযথ সময়সীমা হ্যান্ডেল করতে চান
জোনাথন বেন

40

এই মুহুর্তে অনুরোধ অবজেক্টে সরাসরি এটি করার একটি পদ্ধতি রয়েছে:

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

এটি শর্টকাট পদ্ধতি যা সকেট ইভেন্টের সাথে আবদ্ধ হয় এবং তারপরে সময়সীমা তৈরি করে।

তথ্যসূত্র: নোড.জেএস v0.8.8 ম্যানুয়াল এবং ডকুমেন্টেশন


4
অনুরোধ.সেটটাইমআউট "সকেটের সময়সীমা মিলিসেকেন্ডের নিষ্ক্রিয়তার পরে সকেটকে টাইমআউটে সেট করে।" আমার মনে হয় কার্যকলাপটি নির্বিশেষে এই প্রশ্নটি অনুরোধটির সময়সীমা সম্পর্কে।
অস্টেরগার্ড

দয়া করে নোট করুন, নীচের উত্তরগুলির সাথে একইভাবে জড়িত সকেট সরাসরি ব্যবহার করে, req.abort () একটি ত্রুটি ইভেন্ট সৃষ্টি করে, যা ('ত্রুটি') ইত্যাদি দ্বারা পরিচালনা করা উচিত
লুজেন

4
অনুরোধ.সেটটাইমআউট অনুরোধটি বাতিল করে দেবে না, টাইমআউট কলব্যাকে আমাদের ম্যানুয়ালি অ্যাওর্ট কল করতে হবে।
উধায়া

18

রব ইভান্স আনসার আমার জন্য সঠিকভাবে কাজ করে তবে আমি যখন অনুরোধ.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();

4
কোথায় myTimeoutফাংশন আছে? (সম্পাদনা করুন: দস্তাবেজগুলি বলেছেন: টাইমআউট ইভেন্ট নোডেজ.এস ./api/… হিসাবে আবদ্ধ হিসাবে একই )
বেন মিরিক্রফট

লক্ষ্য করুন যে ECONNRESETউভয় ক্ষেত্রেই ঘটতে পারে: ক্লায়েন্ট সকেট বন্ধ করে এবং সার্ভার সংযোগ বন্ধ করে দেয়। এটি ক্লায়েন্ট দ্বারা কল করে abort()সেখানে করা হয়েছে কিনা তা নির্ধারণের জন্য স্পিসিয়াল abortইভেন্ট রয়েছে
কিরিল

9

আরও সহজ পদ্ধতি আছে।

সেটটাইমআউট ব্যবহার করা বা সরাসরি সকেটের সাথে কাজ করার পরিবর্তে,
ক্লায়েন্টের ব্যবহারগুলিতে আমরা 'বিকল্পগুলিতে' টাইমআউট ব্যবহার করতে পারি

নীচে 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

@ ডাউয়ের উত্তরটি এখানে বিশদভাবে জানাচ্ছি যেখানে আপনি কোনও 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));
  });


বাঁধাই (রেকর্ড) যুক্ত করা আমার পক্ষে কোনও পরিবর্তন করেনি। এই ক্ষেত্রে বাঁধাই কি করে?
স্পাইরাইল

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

আমি যদি সকেটের সময়সীমা ব্যবহার করি এবং আমি একের পর এক দুটি অনুরোধ জারি করি (প্রথমটি শেষ করার অপেক্ষা না করে), দ্বিতীয় অনুরোধটির সকেটটি অপরিজ্ঞাত (অন্তত আমি সময়সীমা নির্ধারণ করার চেষ্টা করার মুহূর্তে) পেয়েছি .. সম্ভবত সেখানে থাকতে হবে সকেটে ("রেডি") এর মতো কিছু ... জানি না।
ক্লোদিও

@ ক্লাডিও আপনি একাধিক অনুরোধ করা হচ্ছে তা দেখানোর জন্য আপনার কোডটি আপডেট করতে পারবেন?
ওন্টেরিয়া_

4
অবশ্যই ... এটি একটি বিট দীর্ঘ এবং আমি paste2.org ব্যবহৃত এই একটা সমস্যা হয় না: paste2.org/p/1448487
ক্লডিও

@ ক্লদিও হুম ঠিক আছে, একটি পরীক্ষার পরিবেশ স্থাপন এবং কিছু পরীক্ষার কোড লেখার কাজ শুরু হতে চলেছে, তাই আমার উত্তরটি আগামীকাল (প্যাসিফিক সময়) এফওয়াইআই হিসাবে আসতে পারে
ওন্টেরিয়া_

@ ক্লাডিও আপনার কোডটি আপনার ত্রুটির সাথে মিলেছে বলে মনে হচ্ছে না actually এটি বলছে যে সেটটাইমআউট একটি অনির্ধারিত মানের উপর কল করা হচ্ছে, তবে আপনি যেভাবে এটি কল করছেন এটি বিশ্বব্যাপী সংস্করণের মাধ্যমে, সুতরাং আমাকে আর বিভ্রান্ত করে রেখে অপরিবর্তিত হওয়ার কোনও উপায় নেই।
ওন্টেরিয়া_
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.