0

我正在编写一个适度的 firefox 插件,但在获取插件脚本的“流程”中使用的结果时遇到了一些问题。

我的代码负责将 sqlite 数据库作为模块进行查询,但我不知道如何在其中创建回调,以便插件脚本中的 pagemod 可以使用它并将其传递给内容脚本。

基本上这就是我所拥有的:

  • 主.js:
var pageMod = require("sdk/page-mod");
var self = require("sdk/self");
var myDbScript = require('./myDbScript');

pageMod.PageMod({
    include: "*.example.com/*",
    contentScriptFile:  [self.data.url('jquery-1.10.2.min.js'),
                        self.data.url('myContentScript.js')],
    onAttach: function(worker) {
        // Query the database on behalf of the content script
        worker.port.on('queryTheDB', function(message) {            
            // Get the data from the DB (é is some test value here)
            // Not working because asynchronous querying of the DB
            var resultFromDB = myDbScript.getResult(2);

            // Send the result to the content script
            worker.port.emit('hereIsYourResult', resultFromDB);
        });
    }
});
  • myDBScript.js
// Get required components
var {components} = require("chrome");
components.utils.import("resource://gre/modules/FileUtils.jsm");
components.utils.import("resource://gre/modules/Services.jsm");

// Some code to get the DB

// Create statement to retrieve country based on the IP
var statement = dbConnection.createStatement("SELECT col1, col2 FROM table WHERE col1 = :given_col1");

function getResult(submittedValue) {    
    // Bind parameters
    statement.params.given_col1 = submittedValue;   

    // Execute
    statement.executeAsync({
        handleResult: function(aResultSet) {
            for (let row = aResultSet.getNextRow();
                 row;
                 row = aResultSet.getNextRow()) {

            var resultFromDB = row.getResultByName("col2");
            }
        },

        handleError: function(aError) {
            print("Error: " + aError.message);
            return 'error';
        },

        handleCompletion: function(aReason) {
            if (aReason != components.interfaces.mozIStorageStatementCallback.REASON_FINISHED) {
                print("Query canceled or aborted!");
                return 'canceledOrAborted';
            } else {
                // Sending the result to the add-on script so that it can
                // pass it to the content script
                notifyingTheAddonScript(resultFromDB);
            }
        }
    });
}

// Enable the use of the getResult function
exports.getResult = getResult;

问题是我看不到如何让插件脚本知道结果已经准备好。请多多包涵,我是这方面的菜鸟……

4

1 回答 1

1

由于我没有完整的来源,我无法测试。所以你必须自己修复我犯的任何错误;)

首先,让我们添加一个回调。

// @param {function(result, error)} callback
// Called upon query completion.
// if |error| is a string, then the query failed.
// Else |result| will contain an array of values. 
function getResult(submittedValue, callback) { // changed   
  // Bind parameters
  statement.params.given_col1 = submittedValue;   

  var rv = [], err = null; // added
  // Execute
  statement.executeAsync({
    handleResult: function(aResultSet) {
      for (let row = aResultSet.getNextRow();
        row;
        row = aResultSet.getNextRow()) {

        rv.push(row.getResultByName("col2")); // changed
      }
    },

    handleError: function(aError) {
      print("Error: " + aError.message);
      err = aError.message; // changed
    },

    handleCompletion: function(aReason) {
      if (aReason != components.interfaces.mozIStorageStatementCallback.REASON_FINISHED) {
        print("Query canceled or aborted!");
        err = err || 'canceled or aborted'; // changed
      }
      callback(err ? null : rv, err); // replaced
    }
  });
}

让我们现在在pagemod

onAttach: function(worker) {
  // Query the database on behalf of the content script
  worker.port.on('queryTheDB', function(message) {            
    // Get the data from the DB (é is some test value here)
    // Not working because asynchronous querying of the DB
    myDbScript.getResult(2, function callback(result, error) {
      if (error) {
        worker.port.emit("hereIsYourError", error);
        return;
      }
      worker.port.emit("hereIsYourResult", result);
    });
  });
}

您可能需要采取一些预防措施来避免触发多个查询。虽然这样做是可以的,但可能会损害性能;)

由于我们的回调看起来有点像 a ,因此使用promisepromise实际上可能是一个好主意,甚至可以使用Sqlite.jsm模块和一些Task.jsm魔法。

于 2013-10-19T01:38:29.610 回答