Node-RED:Руководство пользователя/Написание функций: различия между версиями
Myagkij (обсуждение | вклад) Нет описания правки |
Нет описания правки |
||
Строка 18: | Строка 18: | ||
Код, вставленный в ноду '''«Function»''' – это тело функции. Самая простая функция просто возвращает сообщение как оно есть: | Код, вставленный в ноду '''«Function»''' – это тело функции. Самая простая функция просто возвращает сообщение как оно есть: | ||
<syntaxhighlight lang="javascript | <syntaxhighlight lang="javascript"> | ||
return msg; | return msg; | ||
</syntaxhighlight> | </syntaxhighlight> | ||
Строка 28: | Строка 28: | ||
Возвращаемое сообщение не обязательно должно быть тем же объектом, который был на входе. Функция может создать на основе входного сообщения совершенно новый объект. Например: | Возвращаемое сообщение не обязательно должно быть тем же объектом, который был на входе. Функция может создать на основе входного сообщения совершенно новый объект. Например: | ||
<syntaxhighlight lang="javascript | <syntaxhighlight lang="javascript"> | ||
var newMsg = { payload: msg.payload.length }; | var newMsg = { payload: msg.payload.length }; | ||
return newMsg; | return newMsg; | ||
Строка 41: | Строка 41: | ||
К примеру, функция ниже устроена таким образом, что если в свойстве '''«Topic»''' сообщения значится '''«banana»''', то это сообщение будет отправлено на второй выходной порт, а не на первый. | К примеру, функция ниже устроена таким образом, что если в свойстве '''«Topic»''' сообщения значится '''«banana»''', то это сообщение будет отправлено на второй выходной порт, а не на первый. | ||
<syntaxhighlight lang="javascript | <syntaxhighlight lang="javascript"> | ||
if (msg.topic === "banana") { | if (msg.topic === "banana") { | ||
return [ null, msg ]; | return [ null, msg ]; | ||
Строка 51: | Строка 51: | ||
Код ниже отправит исходное сообщение как есть на первый выходной порт, а сообщение, содержащее размер '''«payload»''' – на второй выходной порт. | Код ниже отправит исходное сообщение как есть на первый выходной порт, а сообщение, содержащее размер '''«payload»''' – на второй выходной порт. | ||
<syntaxhighlight lang="javascript | <syntaxhighlight lang="javascript"> | ||
var newMsg = { payload: msg.payload.length }; | var newMsg = { payload: msg.payload.length }; | ||
return [msg, newMsg]; | return [msg, newMsg]; | ||
Строка 62: | Строка 62: | ||
Код ниже отправит сообщения '''«msg1»''', '''«msg2»''' и '''«msg3»''' на первый выходной порт, а сообщение '''«msg4»''' будет отправлено на второй выходной порт. | Код ниже отправит сообщения '''«msg1»''', '''«msg2»''' и '''«msg3»''' на первый выходной порт, а сообщение '''«msg4»''' будет отправлено на второй выходной порт. | ||
<syntaxhighlight lang="javascript | <syntaxhighlight lang="javascript"> | ||
var msg1 = { payload:"первое – на выходной порт 1" }; | var msg1 = { payload:"первое – на выходной порт 1" }; | ||
var msg2 = { payload:"второе – на выходной порт 1" }; | var msg2 = { payload:"второе – на выходной порт 1" }; | ||
Строка 72: | Строка 72: | ||
Код ниже разбивает свойство '''«payload»''' полученного сообщения на два отдельных слова и возвращает по отдельному сообщению для каждого из этих слов: | Код ниже разбивает свойство '''«payload»''' полученного сообщения на два отдельных слова и возвращает по отдельному сообщению для каждого из этих слов: | ||
<syntaxhighlight lang="javascript | <syntaxhighlight lang="javascript"> | ||
var outputMsgs = []; | var outputMsgs = []; | ||
var words = msg.payload.split(" "); | var words = msg.payload.split(" "); | ||
Строка 87: | Строка 87: | ||
Поэтому вам нужно будет воспользоваться функцией [[node.send()]] – чтобы передать ей сообщение/сообщения, которые нужно отправить. Например: | Поэтому вам нужно будет воспользоваться функцией [[node.send()]] – чтобы передать ей сообщение/сообщения, которые нужно отправить. Например: | ||
<syntaxhighlight lang="javascript | <syntaxhighlight lang="javascript"> | ||
doSomeAsyncWork(msg, function(result) { | doSomeAsyncWork(msg, function(result) { | ||
node.send({payload:result}); | node.send({payload:result}); | ||
Строка 96: | Строка 96: | ||
Кроме того, если вы собрались воспользоваться асинхронной функцией, то вам, возможно, нужно будет удалить все необслуженные запросы и закрыть все соединения, пока вы снова не выполните развертку этого потока. Это можно сделать при помощи обработчика событий '''«close»'''. | Кроме того, если вы собрались воспользоваться асинхронной функцией, то вам, возможно, нужно будет удалить все необслуженные запросы и закрыть все соединения, пока вы снова не выполните развертку этого потока. Это можно сделать при помощи обработчика событий '''«close»'''. | ||
<syntaxhighlight lang="javascript | <syntaxhighlight lang="javascript"> | ||
node.on('close', function() { | node.on('close', function() { | ||
// Удаляем весь асинхронный код: | // Удаляем весь асинхронный код: | ||
Строка 107: | Строка 107: | ||
Если вам нужно с помощью ноды '''«Function»''' выполнить логирование в терминал, для этого можно воспользоваться одной из следующих функций: | Если вам нужно с помощью ноды '''«Function»''' выполнить логирование в терминал, для этого можно воспользоваться одной из следующих функций: | ||
<syntaxhighlight lang="javascript | <syntaxhighlight lang="javascript"> | ||
node.log("Something happened"); | node.log("Something happened"); | ||
// "Что-то произошло" | // "Что-то произошло" | ||
Строка 124: | Строка 124: | ||
Если функция наткнется на ошибку, останавливающую работу текущего потока, то ничего не вернет. Чтобы активировать ноду '''«Catch»''', находящуюся в той же вкладке, эта функция должна вызвать [[node.error()]], вторым параметром которой служит исходное сообщение. | Если функция наткнется на ошибку, останавливающую работу текущего потока, то ничего не вернет. Чтобы активировать ноду '''«Catch»''', находящуюся в той же вкладке, эта функция должна вызвать [[node.error()]], вторым параметром которой служит исходное сообщение. | ||
<syntaxhighlight lang="javascript | <syntaxhighlight lang="javascript"> | ||
node.error("ошибка!", msg); | node.error("ошибка!", msg); | ||
</syntaxhighlight> | </syntaxhighlight> | ||
Строка 147: | Строка 147: | ||
Чтобы прочесть значение из контекста, воспользуйтесь следующей функцией: | Чтобы прочесть значение из контекста, воспользуйтесь следующей функцией: | ||
<syntaxhighlight lang="javascript | <syntaxhighlight lang="javascript"> | ||
var myCount = flow.get("count"); | var myCount = flow.get("count"); | ||
</syntaxhighlight> | </syntaxhighlight> | ||
Строка 153: | Строка 153: | ||
Чтобы записать значение в контекст: | Чтобы записать значение в контекст: | ||
<syntaxhighlight lang="javascript | <syntaxhighlight lang="javascript"> | ||
flow.set("count", 123); | flow.set("count", 123); | ||
</syntaxhighlight> | </syntaxhighlight> | ||
Строка 159: | Строка 159: | ||
Код ниже считает, сколько раз была запущена нода «Function»: | Код ниже считает, сколько раз была запущена нода «Function»: | ||
<syntaxhighlight lang="javascript | <syntaxhighlight lang="javascript"> | ||
// Если счетчика еще нет, инициализируем его со значением «0»: | // Если счетчика еще нет, инициализируем его со значением «0»: | ||
var count = context.get('count')||0; | var count = context.get('count')||0; | ||
Строка 174: | Строка 174: | ||
Начиная с версии 0.19 в [[Node-RED]] стало возможно одновременно сохранять/считывать несколько значений. Например, считывание теперь выполняется вот так: | Начиная с версии 0.19 в [[Node-RED]] стало возможно одновременно сохранять/считывать несколько значений. Например, считывание теперь выполняется вот так: | ||
<syntaxhighlight lang="javascript | <syntaxhighlight lang="javascript"> | ||
// Node-RED 0.19 или новее: | // Node-RED 0.19 или новее: | ||
var values = flow.get(["count", "colour", "temperature"]); | var values = flow.get(["count", "colour", "temperature"]); | ||
Строка 184: | Строка 184: | ||
А запись вот так: | А запись вот так: | ||
<syntaxhighlight lang="javascript | <syntaxhighlight lang="javascript"> | ||
// Node-RED 0.19 или новее: | // Node-RED 0.19 или новее: | ||
flow.set(["count", "colour", "temperature"], [123, "red", "12.5"]); | flow.set(["count", "colour", "temperature"], [123, "red", "12.5"]); | ||
Строка 195: | Строка 195: | ||
Если данные контекста требуют асинхронного доступа, то в функции [[get()]] и [[set()]] нужно будет добавить дополнительный параметр – функцию обратного вызова. | Если данные контекста требуют асинхронного доступа, то в функции [[get()]] и [[set()]] нужно будет добавить дополнительный параметр – функцию обратного вызова. | ||
<syntaxhighlight lang="javascript | <syntaxhighlight lang="javascript"> | ||
// Считывание одного значения: | // Считывание одного значения: | ||
flow.get("count", function(err, myCount) { ... }); | flow.get("count", function(err, myCount) { ... }); | ||
Строка 213: | Строка 213: | ||
Асинхронная версия для кода, считающего, сколько раз была запущена нода '''«Function»''', будет выглядеть следующим образом: | Асинхронная версия для кода, считающего, сколько раз была запущена нода '''«Function»''', будет выглядеть следующим образом: | ||
<syntaxhighlight lang="javascript | <syntaxhighlight lang="javascript"> | ||
context.get('count', function(err, count) { | context.get('count', function(err, count) { | ||
if (err) { | if (err) { | ||
Строка 242: | Строка 242: | ||
Для этого в функциях [[get()]] и [[set()]] нужно будет задать дополнительный параметр. В коде ниже это '''«storeName»''', но вам нужно будет вписать вместо него название нужного хранилища. | Для этого в функциях [[get()]] и [[set()]] нужно будет задать дополнительный параметр. В коде ниже это '''«storeName»''', но вам нужно будет вписать вместо него название нужного хранилища. | ||
<syntaxhighlight lang="javascript | <syntaxhighlight lang="javascript"> | ||
// Считывание значения (синхронный режим): | // Считывание значения (синхронный режим): | ||
var myCount = flow.get("count", storeName); | var myCount = flow.get("count", storeName); | ||
Строка 265: | Строка 265: | ||
Нода '''«Function»''' также поддерживает добавление статуса – аналогично другим нодам. Чтобы задать статус, вызовите функцию [[node.status()]]. Например: | Нода '''«Function»''' также поддерживает добавление статуса – аналогично другим нодам. Чтобы задать статус, вызовите функцию [[node.status()]]. Например: | ||
<syntaxhighlight lang="javascript | <syntaxhighlight lang="javascript"> | ||
node.status({fill:"red",shape:"ring",text:"Отключено"}); | node.status({fill:"red",shape:"ring",text:"Отключено"}); | ||
node.status({fill:"green",shape:"dot",text:"Подключено"}); | node.status({fill:"green",shape:"dot",text:"Подключено"}); | ||
Строка 282: | Строка 282: | ||
К примеру, встроенный модуль '''«os»''' можно сделать доступным для всех функций, добавив в файл '''«settings.js»''' следующее: | К примеру, встроенный модуль '''«os»''' можно сделать доступным для всех функций, добавив в файл '''«settings.js»''' следующее: | ||
<syntaxhighlight lang="javascript | <syntaxhighlight lang="javascript"> | ||
functionGlobalContext: { | functionGlobalContext: { | ||
osModule:require('os') | osModule:require('os') | ||
Строка 290: | Строка 290: | ||
В результате к этому модулю можно будет обратиться внутри функции следующим образом: | В результате к этому модулю можно будет обратиться внутри функции следующим образом: | ||
<syntaxhighlight lang="javascript | <syntaxhighlight lang="javascript"> | ||
global.get('osModule') | global.get('osModule') | ||
</syntaxhighlight> | </syntaxhighlight> | ||
Строка 296: | Строка 296: | ||
Модули, загружаемые из файла настроек, должны быть установлены в ту же директорию, где находится файл настроек. У большинства пользователей это скорее всего будет пользовательская папка, используемая по умолчанию: '''«~/.node-red»''': | Модули, загружаемые из файла настроек, должны быть установлены в ту же директорию, где находится файл настроек. У большинства пользователей это скорее всего будет пользовательская папка, используемая по умолчанию: '''«~/.node-red»''': | ||
<syntaxhighlight lang="bash | <syntaxhighlight lang="bash"> | ||
cd ~/.node-red | cd ~/.node-red | ||
npm install название_стороннего_модуля | npm install название_стороннего_модуля |
Версия от 20:06, 23 мая 2023
Черновик |
Написание функций[1]
Нода «Function» позволяет применять JavaScript-код к проходящим через нее сообщениям.
Эти сообщения приходят в ноду «Function» в виде объекта под названием «msg». Как правило, у него есть свойство «msg.payload», содержащее тело сообщения.
Другие ноды могут добавить в сообщение собственные свойства (более подробно об этом читайте в документации к этим нодам).
Написание функции
Код, вставленный в ноду «Function» – это тело функции. Самая простая функция просто возвращает сообщение как оно есть:
return msg;
Если функция возвращает «null», то никакого сообщения дальше не пойдет, и поток завершится.
Функция всегда должна возвращать объект «msg». Если она вернет число или строку, это выдаст ошибку.
Возвращаемое сообщение не обязательно должно быть тем же объектом, который был на входе. Функция может создать на основе входного сообщения совершенно новый объект. Например:
var newMsg = { payload: msg.payload.length };
return newMsg;
Примечание: Как правило, при конструировании нового объекта «msg» свойства входящего объекта «msg» всегда претерпевают изменения. Это нарушает работу некоторых потоков – например, потоков с нодами «http in» или «http response», которым на протяжении всего потока нужны свойства «msg.req» и «msg.res».
Отправка сообщений на несколько выходных портов
В меню редактирования ноды «Function» можно, помимо прочего, поменять количество выходных портов. Если у ноды больше одного выходного порта, то функция может вернуть не одно сообщение, а массив сообщений для отправки на разные выходные порты в зависимости от определенных условий.
К примеру, функция ниже устроена таким образом, что если в свойстве «Topic» сообщения значится «banana», то это сообщение будет отправлено на второй выходной порт, а не на первый.
if (msg.topic === "banana") {
return [ null, msg ];
} else {
return [ msg, null ];
}
Код ниже отправит исходное сообщение как есть на первый выходной порт, а сообщение, содержащее размер «payload» – на второй выходной порт.
var newMsg = { payload: msg.payload.length };
return [msg, newMsg];
Отправка нескольких сообщений
Нода «Function» может вернуть несколько сообщений в виде массива сообщений. Если выходной порт отправляет несколько сообщений, то последующие ноды будут получать эти сообщения по очереди – в том порядке, в котором функция их возвращала.
Код ниже отправит сообщения «msg1», «msg2» и «msg3» на первый выходной порт, а сообщение «msg4» будет отправлено на второй выходной порт.
var msg1 = { payload:"первое – на выходной порт 1" };
var msg2 = { payload:"второе – на выходной порт 1" };
var msg3 = { payload:"третье – на выходной порт 1" };
var msg4 = { payload:"четвертое – на выходной порт 2" };
return [ [ msg1, msg2, msg3 ], msg4 ];
Код ниже разбивает свойство «payload» полученного сообщения на два отдельных слова и возвращает по отдельному сообщению для каждого из этих слов:
var outputMsgs = [];
var words = msg.payload.split(" ");
for (var w in words) {
outputMsgs.push({payload:words[w]});
}
return [ outputMsgs ];
Асинхронная отправка сообщений
Если функции нужно выполнить асинхронное действие перед отправкой сообщения, то в конце она не сможет вернуть сообщение.
Поэтому вам нужно будет воспользоваться функцией node.send() – чтобы передать ей сообщение/сообщения, которые нужно отправить. Например:
doSomeAsyncWork(msg, function(result) {
node.send({payload:result});
});
return;
Кроме того, если вы собрались воспользоваться асинхронной функцией, то вам, возможно, нужно будет удалить все необслуженные запросы и закрыть все соединения, пока вы снова не выполните развертку этого потока. Это можно сделать при помощи обработчика событий «close».
node.on('close', function() {
// Удаляем весь асинхронный код:
// отключаем соединения и так далее
});
Логирование событий
Если вам нужно с помощью ноды «Function» выполнить логирование в терминал, для этого можно воспользоваться одной из следующих функций:
node.log("Something happened");
// "Что-то произошло"
node.warn("Something happened you should know about");
// "Произошло что-то, о чем вы должны знать"
node.error("Oh no, something bad happened");
// "О нет, случилось что-то ужасное!"
Функции warn() и error() также будут отправлять сообщения на вкладку «Debug» боковой панели.
Нужны более подробные логи? Воспользуйтесь функциями trace() и debug(). Но если ваш инструмент для чтения логов не настроен на то, чтобы считывать информацию этих уровней логирования (TRACE и DEBUG), то вы эту информацию, соответственно, и не увидите.
Обработка ошибок
Если функция наткнется на ошибку, останавливающую работу текущего потока, то ничего не вернет. Чтобы активировать ноду «Catch», находящуюся в той же вкладке, эта функция должна вызвать node.error(), вторым параметром которой служит исходное сообщение.
node.error("ошибка!", msg);
Хранение данных
Нода «Function» может сохранять данные не только в объект «msg», но и в нужный контекст.
Более подробно о контекстах Node-RED читайте в этой статье.
В ноде «Function» можно использовать три предопределенные переменные, дающие доступ к нужному контексту:
- «context» – локальный контекст ноды
- «flow» – контекст потока
- «global» – глобальный контекст
Во фрагментах кода ниже используется контекст «flow», но их можно применить и к двум другим контекстам – «context» и «global».
Примечание: Эти предопределенные переменные – инструментарий ноды «Function». Если вы создаете собственную ноду, ознакомьтесь с этим руководством (в нем объясняется, как получить доступ к нужному контексту).
Есть два режима доступа к контексту – синхронный и асинхронный. Встроенные контексты Node-RED поддерживают оба этих режима. Некоторые хранилища данных могут поддерживать только асинхронный режим и, если попытаться получить к ним доступ синхронно, они выдадут ошибку.
Чтобы прочесть значение из контекста, воспользуйтесь следующей функцией:
var myCount = flow.get("count");
Чтобы записать значение в контекст:
flow.set("count", 123);
Код ниже считает, сколько раз была запущена нода «Function»:
// Если счетчика еще нет, инициализируем его со значением «0»:
var count = context.get('count')||0;
count += 1;
// Сохраняем измененное значение обратно:
context.set('count',count);
// Делаем это значение частью выходящего объекта «msg»:
msg.count = count;
return msg;
Запись/считывание нескольких значений
Начиная с версии 0.19 в Node-RED стало возможно одновременно сохранять/считывать несколько значений. Например, считывание теперь выполняется вот так:
// Node-RED 0.19 или новее:
var values = flow.get(["count", "colour", "temperature"]);
// values[0] – это значение «count»
// values[1] – это значение «colour»
// values[2] – это значение «temperature»
А запись вот так:
// Node-RED 0.19 или новее:
flow.set(["count", "colour", "temperature"], [123, "red", "12.5"]);
В этом случае все недостающие значения будут выставлены на «null».
Асинхронный доступ к данным контекста
Если данные контекста требуют асинхронного доступа, то в функции get() и set() нужно будет добавить дополнительный параметр – функцию обратного вызова.
// Считывание одного значения:
flow.get("count", function(err, myCount) { ... });
// Считывание нескольких значений:
flow.get(["count", "colour"], function(err, count, colour) { ... })
// Сохранение одного значения:
flow.set("count", 123, function(err) { ... })
// Сохранение нескольких значений:
flow.set(["count", "colour", [123, "red"], function(err) { ... })
Первый параметр функции обратного вызова («err») задается, только если при доступе к контексту выскакивает ошибка.
Асинхронная версия для кода, считающего, сколько раз была запущена нода «Function», будет выглядеть следующим образом:
context.get('count', function(err, count) {
if (err) {
node.error(err, msg);
} else {
// Если счетчика еще нет, инициализируем его со значением «0»:
count = count || 0;
count += 1;
// Сохраняем измененное значение обратно:
context.set('count',count, function(err) {
if (err) {
node.error(err, msg);
} else {
// Делаем сообщение частью выходящего объекта «msg»:
msg.count = count;
// Отправляем сообщение:
node.send(msg);
}
});
}
});
Сохранение нескольких значений в контекст
Начиная с версии 0.19 в Node-RED в контекст стало возможно сохранять сразу несколько значений. К примеру, стало возможно сохранять данные и в память, и в локальную файловую систему.
Для этого в функциях get() и set() нужно будет задать дополнительный параметр. В коде ниже это «storeName», но вам нужно будет вписать вместо него название нужного хранилища.
// Считывание значения (синхронный режим):
var myCount = flow.get("count", storeName);
// Считывание значения (асинхронный режим):
flow.get("count", storeName, function(err, myCount) { ... });
// Сохранение значения (синхронный режим):
flow.set("count", 123, storeName);
// Сохранение значения (асинхронный режим):
flow.set("count", 123, storeName, function(err) { ... })
Глобальный контекст
Вы можете заранее – прямо при запуске Node-RED – загрузить нужные данные в глобальный контекст. Это задается в главном файле настроек «settings.js» в свойстве «functionGlobalContext». Эту функцию можно использовать для загрузки дополнительных модулей для того, чтобы затем использовать их в ноде «Function».
Добавление статуса
Нода «Function» также поддерживает добавление статуса – аналогично другим нодам. Чтобы задать статус, вызовите функцию node.status(). Например:
node.status({fill:"red",shape:"ring",text:"Отключено"});
node.status({fill:"green",shape:"dot",text:"Подключено"});
node.status({text:"Просто текстовый статус"});
node.status({}); // очистка статуса
Более подробно о параметрах этой функции читайте тут.
Изменения статуса можно определять при помощи ноды «Status».
Загрузка дополнительных модулей
Нода «Function» не поддерживает прямую загрузку дополнительных модулей. Они должны быть загружены в файл «settings.js» и добавлены в свойство «functionGlobalContext».
К примеру, встроенный модуль «os» можно сделать доступным для всех функций, добавив в файл «settings.js» следующее:
functionGlobalContext: {
osModule:require('os')
}
В результате к этому модулю можно будет обратиться внутри функции следующим образом:
global.get('osModule')
Модули, загружаемые из файла настроек, должны быть установлены в ту же директорию, где находится файл настроек. У большинства пользователей это скорее всего будет пользовательская папка, используемая по умолчанию: «~/.node-red»:
cd ~/.node-red
npm install название_стороннего_модуля
Справочник по API ноды «Function»
В ноде «Function» можно использовать следующие объекты и функции:
- Объект «node»
- node.id – ID ноды «Function» (добавлено в версии 0.19)
- node.name – название ноды «Function» (добавлено в версии 0.19)
- node.log() – логирование сообщения
- node.warn() – логирование сообщения уровня WARN
- node.error() – логирование сообщения уровня ERROR
- node.debug() – логирование сообщения уровня DEBUG
- node.trace() – логирование сообщения уровня TRACE
- node.on() – регистрация прослушивателя событий
- node.status() – обновление статуса ноды
- node.send() – отправка сообщения
- Объект «context»
- context.get() – считывание свойства из контекста ноды
- context.set() – запись свойства в контекст ноды
- context.keys() – возвращение списка всех ключей их контекста ноды
- context.flow() – то же самое, что и «flow»
- context.global – то же самое, что и «global»
- Объект «flow»
- flow.get() – считывание свойства из контекста потока
- flow.set() – запись свойства в контекст потока
- flow.keys() – возвращение списка всех ключей из контекста потока
- Объект «global»
- global.get() – считывание свойства из глобального контекста
- global.set() – запись свойства в глобальный контекст
- global.keys() – возвращение списка всех ключей из глобального контекста
- RED
- RED.util.cloneMessage() – безопасное клонирование объекта сообщения, чтобы его можно было использовать повторно
Другие модули и функции
В коде ноды «Function» также можно использовать нижеследующие модули и функции:
- Buffer – модуль «Buffer» из Node.js
- console – модуль «console» из Node.js (для логирования лучше пользоваться node.log)
- util – модуль «util» из Node.js
- setTimeout() и clearTimeout() – функции JavaScript для работы с таймаутами
- setInterval() и clearInterval() – функции JavaScript для работы с интервалами
Примечание: Нода «Function» при остановке или повторной развертке автоматически удаляет все незаконченные таймауты и таймеры интервалов.
См.также
Внешние ссылки