Расширение Chrome | Одновременное срабатывание нескольких сигналов тревоги

Я создаю расширение напоминания о задаче. У пользователя есть возможность продолжать добавлять задачи и устанавливать напоминания для каждой задачи. Я использую chrome.storage для хранения этих задач и использую прослушиватель onChanged в хранилище для создания будильника для каждой задачи, добавленной в хранилище. Но проблема в том, что если я установлю напоминание 2 минуты для одной задачи и 3 минуты для другой задачи. Затем через 2 минуты я получаю уведомление для обеих задач, а через 3 минуты я снова получаю уведомления для обеих задач.

background.js

      chrome.storage.onChanged.addListener(function(changes, namespace) {
let id = (changes.tasks.newValue.length)-1
let data = changes.tasks.newValue[id]

if(data.task && data.hrs && data.min){
    let totalMins = (parseInt(data.hrs*60))+parseInt(data.min)
    let alarmTime = 60*1000*totalMins
    chrome.alarms.create("remind"+id,{when:Date.now() + alarmTime})
}

chrome.alarms.onAlarm.addListener(()=>{
    let notifObj = {
        type: "basic",
        iconUrl:"./images/logo5.png",
        title: "Time to complete you  task",
        message: data.task
    }
    chrome.notifications.create('remindNotif'+id, notifObj)
}) 

popup.js

      let hrs = document.querySelector("#time-hrs")
let min = document.querySelector("#time-min")
let submitBtn = document.querySelector("#submitBtn")
let task = document.querySelector("#task")


hrs.value = 0;
min.value = 1


hrs.addEventListener('change',()=>{
  if (hrs.value < 0){
    hrs.value =0;
  }
})

min.addEventListener('change',()=>{
   if (min.value < 1){
      min.value = 1;
   }
})

submitBtn.addEventListener("click", ()=>{
 if(task.value){
    chrome.storage.sync.get('tasks',(item)=>{

        let taskArr = item.tasks ? item.tasks : []
        linkArr.push({task:task.value, hrs:hrs.value, min:min.value})
        chrome.storage.sync.set({ 'tasks' : taskArr })
    })
  };
 });

manifest.json

      {
    "name" : "Link Snooze",
    "description" : "This extension reminds you to open your saved links",
    "manifest_version":2,
    "version":"0.1.0",
    "icons":{
        "16":"./images/logo5.png",
        "48":"./images/logo5.png",
        "128":"./images/logo5.png"
    },
    "browser_action":{
        "default_popup":"popup.html",
        "default_icon":"./images/logo5.png"
    },
    "permissions":["storage", "notifications","alarms"],
    "background" : {
        "scripts": ["background.js"],
        "persistent" : false
    },
    "options_page":"options.html"
}

1 ответ

Проблема.

Вы регистрируете новый onAlarmsслушателя при изменении хранилища в дополнение к старым слушателям. Все они запускаются каждый раз при срабатывании одного сигнала тревоги.

Решение.

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

Очевидно, такие слушатели не смогут использовать переменные из асинхронного обратного вызова напрямую, как в вашем коде. Решение состоит в том, чтобы использовать другой метод присоединения данных к событию, например, создать сигнал тревоги с уже содержащим данные, а именно: data.task.

      chrome.alarms.create(data.task, {delayInMinutes: hrs * 60 + min});

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

Случайные подсказки:

  • Объект можно использовать в качестве имени аларма, если вы вызываете JSON.stringify(obj) при создании и JSON.parse(alarm.name) в onAlarm.

  • Во всплывающем окне вместо ручной настройки значений, выходящих за пределы допустимого диапазона, используйте числовой ввод в формате html:

            <input id="time-min" type=number min=0 max=59 step=1>
    

    Тогда прочтите это как число: document.querySelector("#time-min").valueAsNumber || 0

Другие вопросы по тегам