Перейти до основного вмісту

Фоновий скрипт

Фонові скрипти підходять для скриптів, які мають працювати безперервно. Фонові скрипти — це тип скриптів, специфічний для ScriptCat; вони працюють у пісочниці та не можуть отримати доступ до DOM. Їх можна розробляти за допомогою тих самих GM API, що й Tampermonkey, а примітки щодо сумісності зазначені в документації.

Фоновий скрипт (@background)

Фоновий скрипт оголошується атрибутом @background. Він дозволяє скрипту продовжувати працювати у фоновому режимі після ввімкнення скрипта або запуску браузера.

Запланований скрипт (@crontab)

Запланований скрипт — це різновид фонового скрипта, що підходить для завдань, які потрібно запускати повторювано за часовим циклом.

Запланований скрипт оголошується атрибутом @crontab. Він підтримує планування з точністю до хвилини та секунди та надає розширений синтаксис ScriptCat once / once(...), щоб уникнути запуску більше одного разу в межах одного часового циклу.

⚠️ Примітки:

  • В одному скрипті діє лише перший @crontab
  • Рекомендується, щоб час одноразового виконання скрипта + час повторної спроби не перевищував інтервал cron, інакше виконання можуть перетинатися

Примітки щодо cron-виразів

Реалізація cron у ScriptCat базується на node-cron із невеликим розширенням над стандартним синтаксисом cron.

Формат виразу

Стандартний формат із 5 полів (рекомендовано)

minute hour day month weekday

Розширений формат із 6 полів (не рекомендується)

second minute hour day month weekday

⚠️ Формат із 6 полів не рекомендується Середовища браузера не можуть гарантувати точність до секунди, і це збільшує навантаження на продуктивність — планування фонової сторінки може затримуватися.

Доступний синтаксис для кожного поля

СинтаксисЗначенняПриклад
*Будь-яке значення* (щохвилини/щогодини)
числоКонкретне значення5 (5-та хвилина)
a,b,cКілька дискретних значень1,15,30
a-bБезперервний діапазон10-23
*/nКожні n одиниць*/5
a-b/nДіапазон із кроком10-50/10

Правила дня тижня

  • 1–6: понеділок–субота
  • 0 або 7: неділя

Розширений синтаксис once

Що означає once

Використання once у cron-виразі означає:

У межах поточного часового циклу дозволено лише одне успішне виконання

Навіть якщо пізніші моменти часу в межах того самого циклу все ще відповідають правилу cron, скрипт не запускатиметься знову.

once проти once(...)

СинтаксисОсновне cron-значення для цього поляОпис
once* (будь-яке значення)Запускається на першому збігу в циклі, без конкретного часу
once(expr)exprЗапускається лише в моменти, що відповідають expr у циклі, і лише один раз

once(expr) дозволяє точно вказати моменти-кандидати, водночас забезпечуючи "лише один запуск за цикл". Усі стандартні cron-синтаксиси (числа, діапазони, кроки, списки) підтримуються всередині дужок.

Приклад порівняння:

* once * * * // будь-яка хвилина кожної години; запускається на першому збігу, більше не запускається цієї години
* once(9-17) * * * // між 9:00 і 17:59 щодня, запускається раз на годину
0,30 once * * * // яка з хвилин 0 або 30 збігається першою кожної години, та й запускається; більше не запускається цієї години

Позиція once = Часовий цикл, який вона обмежує

Де б не розміщувався once / once(...), це означає "запускати лише один раз у межах цієї часової гранулярності".

Позиція onceПоведінка
поле хвилиниЗапускається лише раз на хвилину
поле годиниЗапускається лише раз на годину
поле дняЗапускається лише раз на день
поле місяцяЗапускається лише раз на місяць
поле дня тижняЗапускається лише раз на тиждень

Приклади:

* once * * * // запускається лише раз на годину
* * once * * // запускається лише раз на день
* 9-18 once * * // запускається лише один раз між 9:00 і 18:59 щодня

once у поєднанні з діапазонами / списками / кроками

once / once(...) можна поєднувати з будь-яким cron-синтаксисом, але є лише одне правило:

У межах одного циклу, щойно запуск успішний, усі подальші моменти, що збігаються, ігноруються

Приклад 1: Діапазон

* 10 once * *

Значення:

  • Щодня 10:00–10:59 є моментами-кандидатами
  • Після першого збігу дня
  • 10:05–10:59 більше не запускатимуться

Приклад 2: Список

* 1,3,5 once * *

Значення:

  • Щодня 1:00, 3:00 і 5:00 є моментами-кандидатами
  • Якщо 1:00 уже запускався
  • 3:00 і 5:00 буде пропущено

Приклад 3: Крок

* */4 once * *

Значення:

  • Щодня 0:00, 4:00, 8:00, 12:00, 16:00 і 20:00 є моментами-кандидатами
  • Після першого запуску дня
  • Подальші моменти не запускатимуться

Приклад 4: once(...) для вказання моментів-кандидатів

* once(9-17) * * *

Значення:

  • Щодня 9:00–17:00 є годинами-кандидатами
  • Цикл скидається щогодини; у межах години перший збіг зупиняє подальші запуски
  • Ефект: запускається раз на годину між 9:00 і 17:00 щодня, загалом 9 разів
* 9-18 once * *

Значення:

  • Щодня 9:00–18:59 є моментами-кандидатами
  • once у полі дня фіксує цикл як один раз на день
  • Після першого збігу дня нічого більше не запускається до 18:59

Приклади @crontab

Звичайні

//@crontab * * * * * // запускається раз на хвилину
//@crontab * * * * * * // запускається раз на секунду (не рекомендується)
//@crontab 0 */6 * * * // запускається щогодини кожні 6 годин
//@crontab 15 */6 * * * // запускається на 15-й хвилині кожні 6 годин
//@crontab * once * * * // запускається щонайбільше раз на годину
//@crontab * * once * * // запускається щонайбільше раз на день
//@crontab * 10 once * * // запускається лише один раз у межах 10:00 щодня (напр., якщо запустився о 10:04, не запускатиметься знову з 10:05 до 10:59)
//@crontab * */4 once * * // перевіряє щонайбільше раз на 4 години щодня (напр., якщо запустився о 4:00, не запускатиметься знову о 8, 12, 16, 20, 24 тощо)

Просунуті

//@crontab * 1,3,5 once * * // запускається один раз о 1:00, 3:00 або 5:00 щодня (напр., якщо запустився о 1:00, не запуститься о 3:00 або 5:00)
//@crontab * 10-23 once * * // запускається один раз між 10:00 і 23:59 щодня (напр., якщо запустився о 10:04, не запускатиметься з 10:05 до 23:59)
//@crontab * once 13 * * // запускається раз на годину 13-го числа кожного місяця
//@crontab * once(9-17) * * * // запускається раз на годину між 9:00 і 17:00 щодня
//@crontab 0,30 once * * * // яка з хвилин 0 або 30 збігається першою щогодини, та й запускається; без повтору цієї години
//@crontab * 9-18 once * * // запускається лише один раз між 9:00 і 18:00 щодня

Рекомендації щодо використання

Гарне застосування для once

  • Завдання, які потребують лише одного запуску на день/годину

  • Скрипти перевірки статусу, синхронізації та звітності

  • Уникнення таких проблем:

    • Браузер не відкривався тривалий час
    • Затримки планування фонової сторінки
    • Дублювання виконання через перезапуск браузера

Не рекомендується для once

  • Завдання, які мають виконуватися в точний момент
  • Скрипти, час виконання яких може значно перевищувати інтервал cron
  • Завдання зі строгими вимогами до узгодженості кількості виконань

Тестування cron-виразів

Під час тестування cron-виразу будь ласка, тимчасово замініть once / once(...) на їхнє основне значення:

  • once*
  • once(expr)expr

Зверніть увагу, що інструменти тестування можуть не підтримувати розширений формат із 6 полів.

Рекомендовані інструменти:

На сторінці списку скриптів наведіть курсор на стовпець статусу запуску, щоб побачити наступний запланований час виконання скрипта.

Журнали

На сторінці списку скриптів наведення курсору на стовпець статусу запуску показує підказку зі статусом запуску скрипта; натискання відкриває вміст журналу, надрукований через GM_log.

Налагодження скриптів

Фонові скрипти можна налагоджувати безпосередньо зі сторінки редактора скриптів, але це має такі обмеження:

  • value синхронізується неправильно
  • меню registerMenu не спрацьовують належним чином

Щоб налагодити реальне середовище виконання, увімкніть Режим розробника в налаштуваннях розширення, потім відкрийте сторінку background.html розширення для налагодження.

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

image-20210903144155450

Promise

Настійно рекомендується такий шаблон, оскільки він також дозволяє менеджеру скриптів контролювати виконання скрипта. Якщо скрипт виконує будь-яку асинхронну операцію, він має повертати Promise.

// ==UserScript==
// @name Background Script
// @namespace wyz
// @version 1.0.0
// @author wyz
// @background
// ==/UserScript==
return new Promise((resolve, reject) => {
if (Math.round((Math.random() * 10) % 2)) {
resolve("ok"); // успішно
} else {
reject("error"); // невдача, з причиною помилки
}
});
// ==UserScript==
// @name Scheduled script that runs once a day
// @namespace wyz
// @version 1.0.0
// @author wyz
// @crontab * * once * *
// ==/UserScript==
return new Promise((resolve, reject) => {
if (Math.round((Math.random() * 10) % 2)) {
resolve("ok"); // успішно
} else {
reject("error"); // невдача, з причиною помилки
}
});
// ==UserScript==
// @name Call an API
// @namespace wyz
// @version 1.0.0
// @author wyz
// @crontab * * once * *
// ==/UserScript==
return new Promise((resolve, reject) => {
GM_xmlhttpRequest({
url: "https://bbs.tampermonkey.net.cn/",
onload() {
resolve("ok"); // успішно
},
onerror() {
reject("error"); // невдача, з причиною помилки
},
});
});

Обов'язково викликайте resolve / reject лише після того, як логіка скрипта справді завершилася. Після виклику менеджер вважає виконання скрипта завершеним, і подальші GM-операції більше не діятимуть.

Повторна спроба при помилці

Фонові скрипти ScriptCat підтримують повторну спробу при помилці. Коли скрипт завершується невдачею, він може reject з CATRetryError, щоб запустити повторну спробу.

  • Мінімальний інтервал повторної спроби: 5 секунд
  • Уникайте конфлікту з власним часом виконання скрипта, інакше може виникнути дублювання виконання
// ==UserScript==
// @name Retry example
// @namespace https://bbs.tampermonkey.net.cn/
// @version 0.1.0
// @description try to take over the world!
// @author You
// @crontab * * once * *
// @grant GM_notification
// ==/UserScript==

return new Promise((resolve, reject) => {
GM_notification({
title: "retry",
text: "Retrying in 10 seconds",
});
reject(new CATRetryError("xxx error", 10));
});