从回调调用的addListener的sendResponse返回上一条消息

时间:2013-11-11 12:34:11

标签: google-chrome google-chrome-extension webkit

一开始我认为问题出在chrome.runtime.sendMessage()我发送了两条消息。一个用于访问localstorage,另一个用于获取/读取文件数据,但在我将它们合并到一个sendMessage后没有任何更改,这意味着实际问题是window.webkitRequestFileSystem()它返回了以前的文件而不是现在的那个。

是否有更好/更快的方式存储客户端? (我愿意尝试一切)?

的manifest.json

{
  "manifest_version": 2,

...
  "content_scripts": [
    {
      "matches": ["http://*/*", "https://*/*"],
      "js": ["content.js"],
      "run_at": "document_end"
    }
  ],
  "background": {
    "scripts": ["background.js"]
  },
  "permissions": [
    "unlimitedStorage"
  ]
}

background.js

var theme = '';

chrome.runtime.onMessage.addListener(function(request, sender, sendResponse) {
    if(request.method == "getTheme") {
      themes    = JSON.parse(localStorage["themes"]);
      themeName = "";
      for (var i = themes.length - 1; i >= 0; i--) {
        if(request.url.indexOf(themes[i]) !== -1) {
          themeName = themes[i];
        }
      };
      window.webkitRequestFileSystem(window.PERSISTENT, 0, readFromFileStorage.bind(window, themeName), errorHandler);

      sendResponse({data: theme});
    }
});

  function readFromFileStorage(filename, fs) {

    fs.root.getFile(filename, {}, function(fileEntry) {

      fileEntry.file(function(file) {
         var reader = new FileReader();

          reader.onloadend = function(e) {
            theme = this.result;
          };

         reader.readAsText(file);
      }, errorHandler);
    }, errorHandler);
  }

    function errorHandler(e) {
      console.log('Error: ' + e.message);
    }

content.js

chrome.runtime.sendMessage({method: "getTheme", url: location.href}, function(response) {
  console.log(response.data);
});

1 个答案:

答案 0 :(得分:5)

由于您的问题不是SSCCE,因此很难对其进行测试,但我认为您的问题是了解JS异步性质。

那么你的代码将如何实际执行:

  1. 首先执行window.webkitRequestFileSystem(PERSISTENT, 0, successCallback, errorHandler);
  2. 然后sendResponse({data: theme});将使用theme
  3. 中存储的内容发送回复
  4. 然后根据文件请求成功,调用successCallback errorHandlersuccessCallback。如果将调用theme,那么您的sendResponse变量将填充您想要的值。但是,由于你已经发送了回复,这将会很晚。
  5. 下次传递消息时,您将收到上一个主题值(第2点),因为您的代码只有在您发送值后才会找到新值。

    解决方案可能是在您找到所需的值后调用successCallback内的sendResponse(您必须将readFromFileStorage传递到sendResponse)。如果您这样做,那么您可以考虑将errorHandler添加到sendResponse函数中,以确保您的代码始终获得有效的响应。

    如果您将addListener移动到回调中,则必须从addListener函数返回true,否则在{{1}}返回通道将被关闭且响应将不会发送。