На сайте http://wiki.amperka.ru/js:timer для модуля @amperka/timer указана функция Timer.interval([val],[units]). Но интерпретатор ее не находит, пишет "caught Error: Function "interval" not found!". При том, что функции Timer.create, Timer.run работают. На GitHub https://github.com/amperka/espruino-modcat/blob/master/modules/@amperka/timer.js данная функция тоже отсутствует. Где можно взять более новую библиотеку @amperka/timer?
Здравствуйте. Действительно эта библиотека попала в продакшен без метода interval. Я его дописал и сейчас отправил библиотекуна код ревью, так что скоро будет доступна исправленная версия. Сейчас можете ее получить на GitHub в пулл-реквесте timer. Отдельно хочу добавить, что библиотека таймера - это просто обертка над функциями setInterval, changeInterval и clearInterval, по этому для реализации таймера ее использовать совершенно не обязательно. Для производительности лучше делать так: Код (Javascript): // Функция, выполняемая по таймеру var onTick = function() { LED1.write(!LED1.read()); }; // Запустим таймер var intId = setInterval(onTick, 1000); // Изменим период changeInterval(intId, 500); // Остановим таймер clearInterval(intId); Соответственно для изменения периода интервала и его остановки, необходимо знать его идентификатор, который возвращается при запуске интервала. Период указывается в миллисекундах (тысячных долях секунды). Иногда возникает ситуация, что необходимо остановить или изменить интервал, но его может не быть (был остановлен в каком-то другом месте и ID не обнулен). В таком случае стоит использовать конструкцию try {} catch {}. Она позволяет перехватывать ошибки и не останавливать выполнение программы: Код (Javascript): // Функция, выполняемая по таймеру var onTick = function() { LED1.write(!LED1.read()); }; // Запустим таймер var intId = setInterval(onTick, 1000); // Отобразим ID таймера print('IntID = ' + intId); // Попробуем удалить все таймеры с ID от 0 до 9 for (i = 0; i<10; i++) { try { // Вызываем остановку таймера clearInterval(i); } catch (e) { // Если во время остановки произошла ошибка (таймер не существует) print ('Interval ID: ' + i + ' is not found'); } } Т.е. в try вы берете функцию, которая может вызвать ошибку, а в catch - описываете действия, которые нужно совершить если ошибка произошла. Если нужно просто остановить интервал с определенным ID, то в catch можно ничего не писать. Таким образом программа продолжит свое выполнение и таймер гарантированно остановиться, если он существует.
На платформе mbed упоминается, что не рекомендуется помещать тяжелые операции в функцию таймера (циклы, передачу данных...). Так как, не законченное прерывание может обрываться новым. На платформе JS такое ограничение существует? или она чем-то похоже на RTOS?
Ограничения те же самые, setInterval фактически задействует аппаратный таймер. С другой стороны если у вас передача данных - после срабатывания прерывания по приему (к примеру), программа вернется к выполнению текущего кода. А вот событии Serial.on('data') следует разбить строку на разделители, текущий обрабатываемый фрагмент записать в отдельную переменную, а оставшиеся не обработанные данные - немедленно дописать к буферу. И только после этого вызвать разбор принятых данных. Таким образом, если в процессе разбора придут новые данные - они просто будут добавлены к текущему буферу, а запущенный процесс обработки не прервется.
Переменную для буфера в JS вы создаете самостоятельно. Ниже пример, который обработает данные, передаваемые с задержкой, и с длительным временем обработки: Код (Javascript): // Настроим последовательный порт Serial3.setup(115200); // Буффер, где будут лежать полученные, но не обработанные данные; var buffer = ''; // Разделитель данных, полученых по последовательному порту // В зависимости от передатчиков может быть разный по содержанию var delimiter = '\r\n'; // Переменная, указывающая на то, что медленная функция в процессе работы var slowFuncIsWork = false; // Функция которая оооочень медленно обрабатывает команды var mySlowFunc = function(cmd) { slowFuncIsWork = true; // Медленное действие setTimeout(function() { // Через секунду отобразим параметр cmd print(cmd); // Как обработка закончилась - пометим, что ресурсы не заняты slowFuncIsWork = false; // Симулируем приход новых данных, чтобы проверить буфер, который может // их содержать не обработанными, а фактической передачи уже не будет Serial3.emit('data', ''); }, 1000); }; // На получение данных Serial3.on('data', function(data) { // Немедленно дописываем ими буфер buffer += data; // Если запущена обработка - прерываемся - выполним в следующий раз if (slowFuncIsWork) { return; } // Ищем в буфере разделитель var pos = buffer.indexOf(delimiter); // Если разделитель не найден - прерываемся, ждем дополнения данных if (pos < 0) { return; } // Сохраняем обрабатываемую команду var cmd = buffer.substr(0, pos); // Перед обработкой записываем в буфер остаток данных, которые // еще не обработаны. delimiter.length стоит заменить на число - // длину разделителя, так как его записывать в буфер мы не будем. buffer = buffer.substr(pos + delimiter.length); // Запускаем обработку mySlowFunc(cmd); }); // Для тестирования симулируем прием данных частями с задержкой в 0.1 секунду Serial3.emit('data','Hello\r\nbra'); setTimeout(function() { Serial3.emit('data', 've\r\nnew\r\nworld\r\n'); }, 100);