Реализация блокировки с использованием GM_getValue GM_setValue - PullRequest
0 голосов
/ 18 сентября 2010

У меня есть скрипт greasemonkey, который при запуске проверяет, доступно ли обновление, и предлагает пользователю загрузить обновление, если это так. Обычно это работает нормально, за исключением того, что если пользователь одновременно открывает несколько вкладок (скажем, при запуске браузера или использовании «Открыть все вкладки» для папки закладок), сценарий greasemonkey будет пинговать пользователя на каждой вкладке одновременно, что немного PITA для пользователя.

Я думаю, что единственный канал связи между экземплярами сценария, который у меня есть, это GM_setValue / GM_getValue, который позволяет экземплярам получить доступ к хранилищу ключей / значений.

Что мне нужно сделать, так это придумать схему блокировки (назовем ее GM_setLock / GM_releaseLock), поэтому я могу сделать следующее:

GM_setLock();
const tried_update = GM_getValue(available_version);
GM_setValue(available_version, true);
GM_releaseLock();

if (!tried_update) { prompt_user() }

Без блокировки у меня могло бы быть несколько экземпляров на разных вкладках, все они читали бы GM_getValue(available_version) до того, как какой-либо из них достигнет GM_setValue(available_version, true), поэтому пользователь мог пинговаться несколько раз.

Дело в том, что я не знаю, как реализовать блокировку на макушке, если у меня есть доступ только к тому (что я готов притворяться) к атомарному чтению и атомарной операции записи (и без атомарного написать и вернуть предыдущее значение). Есть идеи?

1 Ответ

1 голос
/ 18 сентября 2010

Вы не можете сделать это с этим синтаксисом в Greasemonkey, но что-то вроде этого должно делать то, что вы хотите:

Заверните проверку обновления (или что-то еще), вот так:

function UpgradeCheckFunction ()
{
    //--- Put payload code here.

    alert ("I just ran an an upgrade check?!");
}

.
Затем определите PerformOnceAcrossTabs(), вот так:

function PerformOnceAcrossTabs (sName, oFunction)
{
    var OldValue    = GM_getValue (sName);
    if (OldValue)
    {
        //--- Optionally also do a timestamp check and clear any "locks" that are X hours old.
        return;
    }

    GM_setValue (sName, new Date().toString() );

    //--- run payload function here.
    (oFunction)();

    //--- Clear "Lock".
    GM_deleteValue (sName);
}

.
Тогда назовите это так:

PerformOnceAcrossTabs ("UpgradeCheckLock", UpgradeCheckFunction);
...