同步同一 Greasemonkey 脚本的多个实例

问题描述 投票:0回答:1

我有一个 Greasemonkey 用户脚本,它在任务队列上运行。该队列是一堆序列化的 JSON 对象,分散在脚本私有首选项空间中,可以使用

GM_getValue
GM_setValue
GM_listValues
进行访问。

我想让这个脚本同时运行(同一台机器,同一浏览器,不同的选项卡),同时仍然保持共享队列。我知道 Javascript 主要在单个线程中运行(Web Workers 除外),但我认为在单独的选项卡中打开的页面并非如此,因此它必须同时运行。

在这种情况下,我如何正确组织对此类对象的共享访问,以防止竞争条件?竞争条件会出现吗?

javascript multithreading concurrency synchronization greasemonkey
1个回答
1
投票

令我自己惊讶的是,似乎没有竞争条件,因为 Javascript 在整个浏览器中单线程运行。我已经使用以下用户脚本对其进行了测试:

// ==UserScript==
// @name        test-concurrency
// @namespace   mw.tools
// @include     /^http://localhost//
// @version     1
// @grant       GM_getValue
// @grant       GM_setValue
// ==/UserScript==

var BLOCK = 1000;
var ATOM = 'foo';
switch (window.location.search) {
    case '?inc':
        setInterval(function() {
            var i;

            for (i = 0; i < BLOCK; i++) {
                GM_setValue(ATOM, GM_getValue(ATOM, 0) + 1);
            }

            document.title = '' + GM_getValue(ATOM, 0) + ' || ' + (GM_getValue(ATOM, 0) % BLOCK);
        }, 1);
        break;

    case '?ver':
        setInterval(function() {
            var v;
            var v0;

            v0 = GM_getValue(ATOM);
            for (i = 0; i < BLOCK; i++) {
                v = GM_getValue(ATOM);
                if (v != v0) {
                    document.title = v0 + ' || broken';
                    alert('BORKEH!!1111oneone');
                }
            }
            document.title = v0;
        }, 1);
        break;
}

使用较大的

BLOCK
值时,无论在哪个选项卡或窗口中运行违规脚本,浏览器似乎都没有响应。

因此,对于同步脚本,保持一些共享标志告诉结构已在使用中就足够了,并进行随机间隔轮询以使其变得空闲(简单的方法,但可能会挨饿),或者使用

postWindow()
广播并保持挂起想要获取“互斥体”的队列,实现监视器(某种程度上,因为每个脚本调用都在关键部分中)。

© www.soinside.com 2019 - 2024. All rights reserved.