@MarcRochkind我想一些知識添加到您的書在Chrome應用集成SQL.js。
這很可能只需很少的努力(考慮到政策和規則的服從)。
爲了任何使用eval
整合,需要沙箱腳本的特定部分。在SQL.js的情況下,它是整個庫。
這可以通過在主要.html
文檔中需要設置的iframe來完成,該文檔被稱爲創建(或主)窗口,例如, chrome.app.window.create('index-app.html', { ..
主文檔和iframe之間的通信基地將使用postMessage發送和接收消息。
比方說,這個iframe的來源被稱爲/iframes/sqljs-sandboxed.html
。 在manifest.json
中,您需要指定sqljs-sandboxed.html
作爲沙箱。指定的沙箱可以運行eval
和eval
樣構建,如new Function
。
{
"manifest_version": 1,
"name": "SQL.js Test",
..
"sandbox": {
"pages": [
"iframes/sqljs-sandboxed.html",
]
}
}
的sqljs-sandboxed.html
使用一個事件監聽器上message
類型的事件作出反應。在這裏,您可以簡單地添加邏輯(爲了簡單起見,我使用了switch語句)來執行任何使用SQL.js構造的任何內容。
的sqljs-sandboxed.html
內容爲例:
<script src="/vendor/kripken/sql.js"></script>
<script>
(function(window, undefined) {
// a test database
var db = new SQL.Database();
// create a table with some test values
sqlstr = "CREATE TABLE hello (a int, b char);";
sqlstr += "INSERT INTO hello VALUES (0, 'hello');";
sqlstr += "INSERT INTO hello VALUES (1, 'world');";
// run the query without returning anything
db.run(sqlstr);
// our event listener for message
window.addEventListener('message', function(event) {
var params = event.data.params,
data = event.data.data,
context = {};
try {
switch(params.cmd) {
case '/do/hello':
// process anything with sql.js
var result = db.exec("SELECT * FROM hello");
// set the response context
context = {
message: '/do/hello',
hash: params.hash,
response: result
};
// send a response to the source (parent document)
event.source.postMessage(context, event.origin);
// for simplicity, resend a response to see if event in
// 'index-app.html' gets triggered a second time (which it
// shouldn't)
setTimeout(function() {
event.source.postMessage(context, event.origin);
}, '1000');
break;
}
} catch(err) {
console.log(err);
}
});
})(window);
</script>
測試數據庫中創建只有一次,事件偵聽器鏡使用一個簡單的開關的API。這意味着爲了使用SQL.js,您需要針對API編寫代碼。這可能乍一看有點不舒服,但從本質上講,這個想法在實施REST服務時是等同的,在我看來,這從長遠來看非常舒適。
爲了發送請求,index-app.html
是發起者。需要指出的是,可以異步地向iframe 發出多個請求。爲了防止交叉,每個請求都以唯一標識符的形式發送一個狀態參數(在我的例子中是unique-ish)。同時在message
事件中附加了一個監聽器,該事件篩選出所需的響應並觸發其指定的回調,如果觸發,則將其從事件堆棧中移除。
對於快速演示,會創建一個對象,用於自動附加和拆除message
事件。最終,listen
函數最終應該過濾特定的字符串值,例如, sandbox === 'sql.js'
(在此示例中未實現),以便加速使用多個沙箱化iframe(例如,用於模板化的handlebars.js)時可能發生的多個message
事件的篩選器選擇。
var sqlRequest = function(request, data, callback) {
// generate unique message id
var hash = Math.random().toString(36).substr(2),
// you can id the iframe as wished
content_window = document.getElementById('sqljs-sandbox').contentWindow,
listen = function(event) {
// attach data to the callback to be used later
this.data = event.data;
// filter the correct response
if(hash === this.data.hash) {
// remove listener
window.removeEventListener('message', listen, false);
// execute callback
callback.call(this);
}
};
// add listener
window.addEventListener('message', listen, false);
// post a request to the sqljs iframe
content_window.postMessage({
params: {
cmd: request,
hash: hash
},
data: data
}, '*');
};
// wait for readiness to catch the iframes element
document.addEventListener('DOMContentLoaded', function() {
// faking sqljs-sandboxed.html to be ready with a timeout
setTimeout(function() {
new sqlRequest('/do/hello', {
allthedata: 'you need to pass'
}, function() {
console.log('response from sql.js');
console.log(this.data);
});
}, '1000');
});
爲了簡單起見,我使用超時來防止在加載iframe之前發送請求。根據我的經驗,最好讓iframe發送一條消息給iframe加載的父文檔,從這裏開始,您可以開始使用SQL.js.
最後,在index-app.html
您指定的iframe
<iframe src="/iframes/sqljs-sandboxed.html" id="sqljs-sandbox"></iframe>
凡index-app.html
的內容可以是
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
</head>
<body>
<iframe src="/iframes/sqljs-sandboxed.html" id="sqljs-sandbox"></iframe>
<h1>Hello, let's code with SQL.js!</h1>
<script src="/assets/js/sqljs-request.js"></script>
</body>
</html>
雖然現在我已經切換到node-webkit,因爲它擴大了使用節點模塊的更多選項的訪問權限,但仍然提供的信息看起來非常合理,並且肯定會嘗試上述解決方案! – Ric 2015-05-12 09:47:18