Как установить тайм-аут для вызова метода javascript? [Дубликат]

Вы на правильном пути. std :: sort будет использовать operator & lt; в качестве функции сравнения по умолчанию. Поэтому для сортировки ваших объектов вам придется либо перегрузить bool operator & lt; (const T & amp ;, const T & amp;) , либо предоставить функтор, который выполняет сравнение, например:

  struct C {int i;  static bool before (const C & amp; c1, const C & amp; c2) {return c1.i & lt;  c2.i;  }};  bool operator & lt; (const C & amp; c1, const C & amp; c2) {return c1.i & gt;  c2.i;  } std :: vector & lt; C & gt;  значения;  std :: sort (values.begin (), values.end ());  // использует оператор & lt;  std :: sort (values.begin (), values.end (), C :: before);   

Преимущество использования функтора заключается в том, что вы можете использовать функцию с доступом к закрытым членам класса.

70
задан Claudio 2 June 2011 в 14:07
поделиться

8 ответов

В этот момент существует способ сделать это непосредственно на объекте запроса:

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

Это метод ярлыков, который привязывается к событию сокета, а затем создает тайм-аут.

Ссылка: Node.js v0.8.8 Manual & amp; Документация

32
ответ дан Andrey Hohutkin 16 August 2018 в 10:42
поделиться
  • 1
    request.setTimeout "устанавливает таймер отключения сокета после таймаута миллисекунд бездействия в сокете. & quot; Я думаю, что этот вопрос связан с тайм-аутом запроса, независимо от его активности. – ostergaard 20 January 2013 в 16:00
  • 2
    Обратите внимание, что так же, как в ответах ниже, в которых непосредственно задействован задействованный сокет, req.abort () вызывает событие ошибки, которое должно обрабатываться нажатием («ошибка») и т. Д. – KLoozen 10 January 2016 в 18:31
  • 3
    request.setTimeout не отменяет запрос, нам нужно вызвать отмену вручную в обратном вызове с таймаутом. – Udhaya 23 February 2016 в 06:52

Для меня - здесь менее запутанный способ сделать 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
ответ дан Ben Muircroft 16 August 2018 в 10:42
поделиться

Существует более простой метод.

Вместо использования setTimeout или работы с сокетом напрямую, мы можем использовать «тайм-аут» в «параметрах» в клиентских целях.

Ниже приведен код как сервер, так и клиент, в 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!

Надеюсь, что это поможет.

6
ответ дан Manohar Reddy Poreddy 16 August 2018 в 10:42
поделиться

Вы должны передать ссылку на запрос, как показано ниже

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

2
ответ дан Mathieu Lescaudron 16 August 2018 в 10:42
поделиться
  • 1
    Добавление bind (req) ничего не изменило для меня. Что связывает в этом случае? – SpiRail 3 April 2018 в 10:10

Любопытно, что произойдет, если вместо этого вы используете прямое 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();
0
ответ дан onteria_ 16 August 2018 в 10:42
поделиться
  • 1
    Если я использую тайм-аут сокета, и я выдаю два запроса один за другим (не дожидаясь завершения первого), второй запрос имеет неопределенный сокет (по крайней мере, на данный момент я пытаюсь установить тайм-аут). Может быть, должно быть что-то вроде («готово») на сокет ... Я не знаю. – Claudio 2 June 2011 в 18:18
  • 2
    @Claudio Можете ли вы обновить свой код, чтобы показать несколько запросов? – onteria_ 2 June 2011 в 18:25
  • 3
    Конечно ... это немного длиннее, и я использовал paste2.org, если это не проблема: paste2.org/p/1448487 – Claudio 2 June 2011 в 18:42
  • 4
    @Claudio Хм, хорошо, настройте тестовую среду и напишите какой-нибудь тестовый код, потому что мой ответ может наступить завтра (Pacific Time) в качестве FYI – onteria_ 2 June 2011 в 18:53
  • 5
    Слишком любезно с тобой :) Спасибо – Claudio 2 June 2011 в 19:52

Используя ваш код, проблема в том, что вы не дождались назначения сокета для запроса, прежде чем пытаться установить материал на объект сокета. Это все 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();

Событие 'socket' запускается, когда запросу присваивается объект сокета.

81
ответ дан Rob Evans 16 August 2018 в 10:42
поделиться
  • 1
    Это действительно имеет смысл. Проблема в том, что теперь я не могу проверить эту конкретную проблему (время проходит ...). Поэтому я могу только ответить на этот вопрос :) Спасибо. – Claudio 29 March 2012 в 14:07
  • 2
    Не беспокойся. Имейте в виду, что это работает только на последней версии узла, насколько я знаю. Я тестировал предыдущую версию (5.0.3-pre), я думаю, и это не вызвало событие сокета. – Rob Evans 29 March 2012 в 17:21
  • 3
    Другой способ справиться с этим - использовать стандартный вызов setTimeout. Вам нужно сохранить идентификатор setTimeout с помощью: var id = setTimeout (...); так что вы можете отменить его, если вы получите данные и т. д. Хороший способ - сохранить его в самом объекте запроса, а затем clearTimeout, если вы получите некоторые данные. – Rob Evans 29 March 2012 в 17:23
  • 4
    Ты пропускаешь ); в конце req.on. Поскольку это не 6 символов, я не могу отредактировать его для вас. – JR Smith 7 May 2015 в 15:57
  • 5
    @JRSmith LOL, как вы правы! Обновлено. :) – Rob Evans 8 May 2015 в 12:55

Rob Evans 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();
18
ответ дан Ron Klein 16 August 2018 в 10:42
поделиться
  • 1
    где функция myTimeout? (edit: docs say: То же, что и привязка к событию таймаута nodejs.org/api/… ) – Ben Muircroft 20 September 2016 в 21:08
  • 2
    Обратите внимание, что ECONNRESET может случиться в обоих случаях: клиент закрывает сокет, а сервер закрывает соединение. Чтобы определить, было ли это сделано клиентом, вызвав abort(), существует специальное abort событие – Derp 8 November 2016 в 10:16

Разрабатывая ответ @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 () также прекрасен.

2
ответ дан SpiRail 16 August 2018 в 10:42
поделиться
Другие вопросы по тегам:

Похожие вопросы: