Как реализовать задержку timeout в Express.js при оброботке запроса?

136
27 декабря 2019, 18:10

У меня есть функция оброботки пост запроса внутри которой я тестирую валидность 2 mail аккаунтов с помощью библиотеки emailjs-imap-client , подключаясь поочередно к первому и второму. Если оба подключения прошли успешно посылаю res.send(true) если в одном из двух произошла ошибка подключения, тогда в блоке catch цепочки промиссов посылаю res.send(false).

app.post('/test', (req, res) => { 
    const data = req.body; 
    const port = data.ssl ? 993 : 143; 
    const client = getImapClient(data.host1, port, data.username1, data.password1); 
    const client2 = getImapClient(data.host2, 993, data.username2, data.password2); 
 
    client.connect() 
      .then(() => { 
        client.close(); 
      }) 
      .then(() => client2.connect() 
        .then(() => { 
          client2.close(); 
        })) 
      .then(() => res.send(true)) 
      .catch((e) => { 
        res.send(false); 
        console.log(e); 
      }); 
});

Но есть одна загвостка: Ошибка вылетает если пробовать подключится к существующему imap серверу но с неправильными данными аккаунта и тут всё ок. Но вот например может существовать почтовый сервер mail.lol.ru который слушает на порту 143 и если к нему подключится но на порт 993 (порт ssl) то начнется просто очень длинное время ожидания.И в итоге мой сервер не может выслать ответ клиенту так как тупо ожидает ответ от почтового сервера . В итоге ошибка подключения конечно появляется но спустя минуты.

Нужно чтобы мой сервер внутри этой миддлвары/функции ждал ответа от почтового сервера не больше 5 секунд а потом если тот еще не ответил отправить клиенту res.send(false) и до свидания. Подскажите как это правильно реализовать . Думаю можно с помощью функции setTimeout но не знаю как.

PS: Как бонус если знакомы с промиссами и библиотекой emailjs-imap-client можете дать советы как лучше реализовать проверку а то какая то мутная цепочка получилась. :)

Answer 1

Не уверен, откуда функция getImapClient - в исходниках библиотеки emailjs-imap-client её нет. Я понимаю, что это Ваша функция, код которой Вы не привели здесь.

Внутри Вашей функции есть вызов

var client = new ImapClient(host[, port][, options])

Иногда полезно просмотреть исходники - там сразу видно, что после инициализации клиента мы можем выполнить ещё одну команду:

client.timeoutConnection = 5 * 1000 //Milliseconds to wait for the IMAP greeting from the server

Всего есть 3 вида таймаутов, которые Вы можете переопределить, посмотрите часть исходного кода библиотеки:

const TIMEOUT_CONNECTION = exports.TIMEOUT_CONNECTION = 90 * 1000; // Milliseconds to wait for the IMAP greeting from the server
const TIMEOUT_NOOP = exports.TIMEOUT_NOOP = 60 * 1000; // Milliseconds between NOOP commands while idling
const TIMEOUT_IDLE = exports.TIMEOUT_IDLE = 60 * 1000; // Milliseconds until IDLE command is cancelled
class Client {
  constructor(host, port, options = {}) {
    this.timeoutConnection = TIMEOUT_CONNECTION;
    this.timeoutNoop = TIMEOUT_NOOP;
    this.timeoutIdle = TIMEOUT_IDLE;
Answer 2

Ответ с настройками лучше, но если отвечать именно на заданный вопрос, то можно подписаться на такой промис:

Promise.race(yourPromise, new Promise((res, rej) => setTimeout(rej, 1000, "timeout")))