Вопрос по timedelay, javascript, sleep, blocking, node.js – Как создать сон / задержку в nodejs, который блокирует?

45

В настоящее время я пытаюсь изучить nodejs и небольшой проект, который яЯ работаю - пишу API для управления некоторыми сетевыми светодиодами.

Микропроцессор, управляющий светодиодами, имеет задержку обработки, и мне нужно разместить команды, отправленные на микро, по крайней мере, на расстоянии 100 мс. В C # I 'Я просто вызывал Thread.Sleep (время), но я не нашел подобную функцию в узле.

Я нашел несколько решений, использующих функцию setTimeout (...) в узле, однако это асинхронно и не блокирует поток (что мне и нужно в этом сценарии).

Кто-нибудь знает о блокировке сна или функции задержки? Желательно что-то, что не просто раскручивает процессор, а имеет точность + -10 мс?

Или вы можете сделать это "узел" Кстати, используйте асинхронный стиль для повторного моделирования логики вашей программы. Passerby
Да, имея дело с оборудованием, вам нужен контроль над деталями низкого уровня. Ваша программа может занять некоторое время выполнения, которое вы должны отрегулировать. Если точное планирование имеет первостепенное значение, node.js может не подходить для ваших нужд. user568109
Тыконечно вам нужно заблокировать поток? Если ты'Если вы новичок в nodejs, то, возможно, вы простоВы еще не привыкли мыслить / проектировать поток в асинхронных терминах :)Спальный пакет здесь:npmjs.org/package/sleep (настоящий сон там, где поддерживается, занят - ожидание окон) Supr
Это неТем не менее, это подразумевает, что он должен блокироваться, если только setTimeout не имеет слишком много накладных расходов. Я только что сделал простой тест:jsapp.us/#s445.js Выполнение этого дает не более 6 мс задержки с использованием setTimeout, в то время как блокировка имеет задержку до 39 мс (в худшем случае, вероятно, из-за того, что сервер занят другими вещами, поэтому может не применяться в случае OP). Но я согласен, что node.js, вероятно, не подходит, если требуется абсолютная 100% точность и надежность. Supr

Ваш Ответ

11   ответов
2

Я нашел что-то почти работающее здесьhttps://stackoverflow.com/questions/21819858/how-to-wrap-async-function-calls-into-a-sync-function-in-node-js-or-ja vascript

`function AnticipatedSyncFunction(){
    var ret;
    setTimeout(function(){
        var startdate = new Date()
        ret = "hello" + startdate;
    },3000);
    while(ret === undefined) {
       require('deasync').runLoopOnce();
    }
    return ret;    
}


var output = AnticipatedSyncFunction();
var startdate = new Date()
console.log(startdate)
console.log("output="+output);`

Единственная проблема - дата печатиправильно, но процесс, по крайней мере, последовательный.

37

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

function LedController(timeout) {
  this.timeout = timeout || 100;
  this.queue = [];
  this.ready = true;
}

LedController.prototype.send = function(cmd, callback) {
  sendCmdToLed(cmd);
  if (callback) callback();
  // or simply `sendCmdToLed(cmd, callback)` if sendCmdToLed is async
};

LedController.prototype.exec = function() {
  this.queue.push(arguments);
  this.process();
};

LedController.prototype.process = function() {
  if (this.queue.length === 0) return;
  if (!this.ready) return;
  var self = this;
  this.ready = false;
  this.send.apply(this, this.queue.shift());
  setTimeout(function () {
    self.ready = true;
    self.process();
  }, this.timeout);
};

var Led = new LedController();

Теперь вы можете позвонитьLed.exec и это'Я буду обрабатывать все задержки для вас:

Led.exec(cmd, function() {
  console.log('Command sent');
});
Надеюсь, @TriCore, NodeJS поддерживает ES6 и /asyncawait сейчас. Таким образом, таймауты и асинхронные операции уже не так сложны. Leonid Beschastny
@TriCore Бог благословит Node за то, что он делает глупости настолько сложными, потому что блокировка одного потока определенно глупа (это неотносится к ответу, который технически неверен, потому чтос неблокирующим). @LeonidBeschastny Собственно, генераторы иco существовал в то время, когда был задан вопрос. В настоящее времяasync..await это конечно путь. Estus Flask
Я могу'Я считаю, что простые вещи настолько сложны в NodeJS. Да благословит Бог C # и / или Java! TriCore
17

Просто используйтеchild_process.execSync и вызвать систему "функция сна.

//import child_process module
const child_process = require("child_process");
// Sleep for 5 seconds
child_process.execSync("sleep 5");

// Sleep for 250 microseconds
child_process.execSync("usleep 250");

// Sleep for a variable number of microseconds
var numMicroSeconds = 250;
child_process.execFileSync("usleep", [numMicroSeconds]);

Я использую это в цикле вверху моего основного сценария приложения, чтобы заставить Node ждать, пока сетевые диски не будут подключены, прежде чем запускать остальную часть приложения.

@sapy Вам необходимо включить модуль child_process. Например,const child_process = require("child_process"); sffc
child_process.execSync (»спать 1 "); ^ ReferenceError: child_process не определен sapy
0

Вы можете просто использоватьyield функция введена в ECMA6 иgen-run библиотека:

let run = require('gen-run');


function sleep(time) {
    return function (callback) {
        setTimeout(function(){
            console.log(time);
            callback();
        }, time);
    }
}


run(function*(){
    console.log("befor sleeping!");
    yield sleep(2000);
    console.log("after sleeping!");
});
26

https://www.npmjs.com/package/sleep.

в вашем коде вы можете использовать

var sleep = require('sleep'); 
sleep.sleep(n)

спать в течение определенного n секунд.

Пришлось установить проблему на Ubuntu. Вот решение.github.com/ErikDubbelboer/node-sleep/issues/... tanaydin
1

даже при разработке жестких аппаратных решений. Увидетьtemporal.js который не используетsetTimeout или жеsetIntervalsetImmediate. Вместо этого он используетsetImmediate или жеnextTick которые дают гораздо более высокое разрешение выполнения задач, и вы можете создать линейный список задач. Но вы можете сделать это, не блокируя поток.

@RomulusUrakagiTs'ай "Необходимо"? Я'Мне было бы интересно увидеть этот пример. Можете ли вы предоставить суть? Brian Genisio
@RomulusUrakagiTs'Вы ошибаетесь. Express по своей природе асинхронный ... в обработчике Express вы можете сделать еще один асинхронный вызов и затем вернуть ответ, когда он завершится ... Я нене знаю, что такое внутреннее (sendFile), но вы можете (например) сделать что-то вроде этого:(request, response) => { setTimeout(() => sendFile('', response).call(this), 1000); }, Другими словами, вы можете ответить наrespond возражать всякий раз, когда вы хотите ... немедленно ИЛИ через 3 года в асинхронном режиме. Brian Genisio
@RomulusUrakagiTs'ай яЯ не уверен, что еще сказать. Node.js - это однопоточная модель асинхронного программирования. Вам не доступны блокировка сна / задержки. На самом деле, большинство моделей IO неТ блок тоже. Есть несколько устаревших обращений к файловой системе, которые необязательно блокируют, но их не рекомендуется использовать (например, в соединении / экспрессе), потому что они блокируют любые входящие запросы. И нетt любые задержки блокировки. Я полагаю тымог Напишиwhile Цикл, который постоянно проверяет текущее время на исходное время, но это будет задержка из-за занятости ... та, которая потребляет тонну процессора. Brian Genisio
this.get({'/somepath': function(){ return sendFile('foobar.json').call(this); }); Это функция ответа, как вы можете заставить ее ждать что-то, не блокируя ее? Romulus Urakagi Ts'ai
-4

потому что в большинстве случаев его используют более одного человека. Вы должны использовать settimeout / setinterval в сочетании с обратными вызовами.

Я понимаю это неЭто хорошая практика, но в этом случаеЭто именно то, что мне нужно. Узел будет управлять сервером udp, отправляя команды микропроцессору, управляющему лампочкой. Микро может обрабатывать только одну команду за раз, поэтому Node нужно блокировать поток, чтобы другие только один человек мог управлять светом одновременно. on3al
blocking the main thread is not good style for ... хороший совет для программного обеспечения, которое должно работать с параллелизмом, но этоидеальный стиль для OP 'с задачей, независимо от того,сделано в ASM, JS или даже PHP. Позволять'положить конец этим бездумнымблокировка это плохо а также "синхронно сатана культы ... Mark K Cowan
2

Это довольно просто реализовать с помощью нативного дополнения, поэтому кто-то сделал это:https://github.com/ErikDubbelboer/node-sleep.git

Если "производство» это набор инструментов командной строки, которые могут использовать администраторы (написанные на узле, чтобы использовать код протокола / клиента из основной кодовой базы), тогда отсутствие синхронного / блокирующего содержимого на узле - это полная PITA ... Асинхронное содержимое - это "очень плохая идея в производстве " в некоторых случаях, учитывая необходимость дополнительного тестирования ... Mark K Cowan
конечно, в большинстве случаев. но "производство » это широкий термин. если ты нене нужно обслуживать клиентов, тогда вы можете блокировать вещи. vkurchatkin
Это нормально, если вы знаете, что делаете, js не только для клиент-серверных приложений. setec
Это в основном полезно для целей отладки или для написания тестов. Это'очень плохая идея использовать блокировку сна на производстве. Leonid Beschastny
это должно быть принятое решение! единственный, который фактически блокирует цикл событий. Bamieh
2

Самый простойистинная синхронизация решение (т.е. нет выхода / асинхронности) я мог бы придумать, что работает во всех ОС 's без каких-либо зависимостей - вызывать процесс узла для оценки in-linesetTimeout выражение:

const sleep = (ms) => require("child_process")
    .execSync(`"${process.argv[0]}" -e setTimeout(function(){},${ms})`);
Это хорошее решение, и использованиеspawnSync() вместо этого избегает избежать проблем:spawnSync(process.argv[0], ['-e', 'setTimeout(function(){},' + ms + ')']); и работает Windows / Linux bonger
56

и этос чемхорошо, так что вы действительно не должныне блокировать поток, но, как кажется, для проекта, управляющего светодиодомs, яв любом случае опубликуюне очень хороший ине должен»т быть использованным (шутки в сторону).

Цикл while блокирует поток, поэтому вы можете создать свою собственную функцию сна

function sleep(time, callback) {
    var stop = new Date().getTime();
    while(new Date().getTime() < stop + time) {
        ;
    }
    callback();
}

использоваться как

sleep(1000, function() {
   // executes after one second, and blocks the thread
});

Я думаю, что это единственный способ заблокировать поток (в принципе), удерживая его в цикле, как это делает Node.В него не встроены какие-либо блокирующие функции, так как это может побороть цель асинхронного поведения.

Есть только 2 способа по-настоящемублок» нить в ноде. Использование спин-блокировки в пользовательском пространстве или ожидания занятости или использование операционной системы (пространства ядра) для отмены планирования потока узла (что обычно выполняется путем запуска системной функции ожидания, но есть и другие альтернативы, такие как функции часов posix или блокировка). вызовы системных вызовов, таких как блокировки ОС или использование дочерних процессов ОС, работающих в спящем режиме). CMCDragonkai
Это работает, и окончательно блокирует поток adeneo
Это теперь довольно легко, благодаря /asyncawait: `` `жду нового обещания (решите => {setTimeout (resol, timeInMilliseconds); }); `` ` iX3
@MarkKCowan - выглядит круче, и это то, к чему привыкло большинство людей в Node adeneo
4

вится однострочным:

function sleep(millis) {
  return new Promise(resolve => setTimeout(resolve, millis));
}

// Usage in async function
async function test {
  await sleep(1000)
  console.log("one second has elapsed")
}

// Usage in normal function
function test2 {
  sleep(1000).then(() => {
    console.log("one second has elapsed")
  });
}

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