Javascript 是否有一种简单的转换方法可以将chrome消息传递转换为safari消息传递语法?

Javascript 是否有一种简单的转换方法可以将chrome消息传递转换为safari消息传递语法?,javascript,google-chrome-extension,safari-extension,safari6,Javascript,Google Chrome Extension,Safari Extension,Safari6,我的Chrome扩展使用消息传递从后台页面上扩展内置的localstorage区域检索各种值 我喜欢chrome消息传递,它允许在sendMessage调用中包含回调函数,如下所示: chrome.runtime.sendMessage({greeting: "hello"}, function(response) { console.log(response.farewell); }); 相应的消息接收代码如下所示(Chrome extensions文档中的示例代码): 我正在

我的Chrome扩展使用消息传递从后台页面上扩展内置的localstorage区域检索各种值

我喜欢chrome消息传递,它允许在sendMessage调用中包含回调函数,如下所示:

chrome.runtime.sendMessage({greeting: "hello"}, function(response) {
    console.log(response.farewell);   
});
相应的消息接收代码如下所示(Chrome extensions文档中的示例代码):

我正在尝试将扩展转换为Safari扩展格式,但我不知道如何将Chrome sendMessage/onMessage函数映射到Safari的扩展格式
safari.self.tab.dispatchMessage(名称、数据)
消息处理功能

甚至可以在Safari的dispatchMessage函数调用中包含回调函数吗?
如果没有,我应该如何克服这个限制

在只提供单向消息传递系统的环境中,您始终可以自己实现“带回调的消息”,方法是将唯一ID与每条消息关联,并将回调存储在将这些ID映射到回调的字典中

在回答的最后,我从我的跨浏览器的源代码中复制粘贴了Safari特定的存储模块,它提供了以下API:

  • config.getItem(键,回调)
  • config.setItem(键、值、回调)
  • config.removietem(键,回调)
  • config.clear(回调)
getItem
的回调包含与键关联的值(如果找到)。其他回调接收一个布尔值,该值指示操作是否成功

源代码带有注释,包含用于处理一些边缘情况的代码片段。如果有任何不清楚的地方,请随时向我提问

config-safari.js() global.html的片段:

<script>
(function(exports) {
    var config = {};
    config.getItem = function(key, callback) {
        var result = safari.extension.settings.getItem(key);
        if (typeof result === 'string') {
            try {
                result = JSON.parse(result);
            } catch (e) {
                // Extremely unlikely to happen, but don't neglect the possibility
                console.log('config.getItem error: ' + e);
                result = undefined;
            }
        }
        callback(result);
    };
    // callback's argument: true on success, false otherwise
    config.setItem = function(key, value, callback) {
        var success = false;
        try {
            value = JSON.stringify(value);
            // Safari (5.1.5) does not enforce the database quota,
            // let's enforce it manually (ok, set the quota per key, since
            // the performance issue only occur when a specific key has an outrageous high value)
            // 1 MB should be sufficient.
            if (value.length > 1e6) {
                throw new Error('QUOTA_EXCEEDED_ERR: length=' + value.length);
            }
            safari.extension.settings.setItem(key, value);
            success = true;
        } catch (e) {
            console.log('config.setItem error: ' + e);
        }
        callback(success);
    };
    // callback's argument: true on success, false otherwise
    config.removeItem = function(key, callback) {
        safari.extension.settings.removeItem(key);
        callback(true);
    };
    // callback's argument: true on success, false otherwise
    config.clear = function(callback) {
        safari.extension.settings.clear();
        callback(true);
    };

    // config's message handler
    function handleConfigRequest(event) {
        var args = event.message.args;
        // Last argument: Always a callback
        args.push(function(result) {
            // Note: All of the config methods send a callback only once
            // Behavior for calling the callback twice is undefined.
            
            // Send a reply to trigger the callback at the sender's end
            event.target.page.dispatchMessage('config-reply', {
                messageID: event.message.messageID,
                result: result
            });
        });
        config[event.message.type].apply(config, args);
    }
    
    // Export
    exports.handleConfigRequest = handleConfigRequest;
})(window);
</script>
<script>
safari.application.addEventListener('message', function(event) {
    switch (event.name) {
        case 'config-request':
            handleConfigRequest(event);
            break;
        /* ... other things removed ... */
    }
}, true);
</script>

(职能(出口){
var config={};
config.getItem=函数(键,回调){
var result=safari.extension.settings.getItem(键);
如果(结果的类型=='string'){
试一试{
result=JSON.parse(result);
}捕获(e){
//极不可能发生,但不要忽视这种可能性
log('config.getItem错误:'+e);
结果=未定义;
}
}
回调(结果);
};
//回调的参数:成功时为true,否则为false
config.setItem=函数(键、值、回调){
var成功=false;
试一试{
value=JSON.stringify(value);
//Safari(5.1.5)不强制执行数据库配额,
//让我们手动执行它(好的,设置每个键的配额,因为
//性能问题仅在特定键的值过高时发生)
//1 MB就足够了。
如果(value.length>1e6){
抛出新错误('QUOTA\u超过了\u ERR:length='+value.length);
}
safari.extension.settings.setItem(键,值);
成功=真实;
}捕获(e){
log('config.setItem错误:'+e);
}
回调(成功);
};
//回调的参数:成功时为true,否则为false
config.removietem=函数(键,回调){
safari.extension.settings.removietem(键);
回调(true);
};
//回调的参数:成功时为true,否则为false
config.clear=函数(回调){
safari.extension.settings.clear();
回调(true);
};
//配置的消息处理程序
函数handleConfigRequest(事件){
var args=event.message.args;
//最后一个参数:始终是回调
参数推送(函数(结果){
//注意:所有配置方法只发送一次回调
//两次调用回调的行为未定义。
//发送回复以在发送方端触发回调
event.target.page.dispatchMessage('config-reply'{
messageID:event.message.messageID,
结果:结果
});
});
config[event.message.type].apply(配置,参数);
}
//出口
exports.handleConfigRequest=handleConfigRequest;
})(窗口);
safari.application.addEventListener('message',函数(事件){
开关(event.name){
案例“配置请求”:
handleconfiggrequest(事件);
打破
/*…其他被移除的东西*/
}
},对);
谢谢!太好了!:)我提出了一个类似的解决方案。我仍在努力,不知何故,我成功地创建了一个无休止的消息传递循环,doh!哦,我相信我最终会找到答案的。虽然我认为我应该试试你的方法,而不是我自己的。更新啊哈,我成功地打破了无休止的循环,耶。再次感谢。
// Adapter for maintaining preferences (Safari 5+)
// All methods are ASYNCHRONOUS
define('config-safari', function() {
    var config = {};
    var callbacks = {};
    ['getItem', 'setItem', 'removeItem', 'clear'].forEach(function(methodName) {
        config[methodName] = function() {
            var args = [].slice.call(arguments);
            var callback = args.pop();
            var messageID = Math.random();
            callbacks[messageID] = callback;
            
            var message = {
                type: methodName,
                messageID: messageID,
                args: args
            };
            safari.self.tab.dispatchMessage('config-request', message);
        };
    });
    config.init = function() {
        if (typeof safari === 'undefined') {
            // Safari bug: safari is undefined when current context is an iframe
            // and src="javascript:''"
            // This error is only expected on YouTube.
            // config.getItem is triggered in main, so we just redefine
            // it. Don't overwrite setItem, etc., so that errors are thrown
            // when these methods are used.
            config.getItem = function(key, callback){
                callback();
            };
            return;
        }
        safari.self.addEventListener('message', function(event) {
            if (event.name === 'config-reply') {
                var messageID = event.message.messageID;
                var callback = callbacks[messageID];
                // Check if callback exists. It may not exist when the script is
                // activated in multiple frames, because every frame receives the message
                if (callback) {
                    delete callbacks[messageID];
                    callback(event.message.result);
                }
            }
        }, true);
    };
    return config;
});
<script>
(function(exports) {
    var config = {};
    config.getItem = function(key, callback) {
        var result = safari.extension.settings.getItem(key);
        if (typeof result === 'string') {
            try {
                result = JSON.parse(result);
            } catch (e) {
                // Extremely unlikely to happen, but don't neglect the possibility
                console.log('config.getItem error: ' + e);
                result = undefined;
            }
        }
        callback(result);
    };
    // callback's argument: true on success, false otherwise
    config.setItem = function(key, value, callback) {
        var success = false;
        try {
            value = JSON.stringify(value);
            // Safari (5.1.5) does not enforce the database quota,
            // let's enforce it manually (ok, set the quota per key, since
            // the performance issue only occur when a specific key has an outrageous high value)
            // 1 MB should be sufficient.
            if (value.length > 1e6) {
                throw new Error('QUOTA_EXCEEDED_ERR: length=' + value.length);
            }
            safari.extension.settings.setItem(key, value);
            success = true;
        } catch (e) {
            console.log('config.setItem error: ' + e);
        }
        callback(success);
    };
    // callback's argument: true on success, false otherwise
    config.removeItem = function(key, callback) {
        safari.extension.settings.removeItem(key);
        callback(true);
    };
    // callback's argument: true on success, false otherwise
    config.clear = function(callback) {
        safari.extension.settings.clear();
        callback(true);
    };

    // config's message handler
    function handleConfigRequest(event) {
        var args = event.message.args;
        // Last argument: Always a callback
        args.push(function(result) {
            // Note: All of the config methods send a callback only once
            // Behavior for calling the callback twice is undefined.
            
            // Send a reply to trigger the callback at the sender's end
            event.target.page.dispatchMessage('config-reply', {
                messageID: event.message.messageID,
                result: result
            });
        });
        config[event.message.type].apply(config, args);
    }
    
    // Export
    exports.handleConfigRequest = handleConfigRequest;
})(window);
</script>
<script>
safari.application.addEventListener('message', function(event) {
    switch (event.name) {
        case 'config-request':
            handleConfigRequest(event);
            break;
        /* ... other things removed ... */
    }
}, true);
</script>