1

最初は、問題はchrome.runtime.sendMessage()2 つのメッセージを送信していることにあると思いました。1 つはファイル データにアクセスするためlocalstorageのもので、もう 1 つはファイル データを取得/読み取るためのものですが、それらを 1 つにマージしても何も変わりませんでしたsendMessage。つまり、実際の問題はwindow.webkitRequestFileSystem()、現在のファイルではなく前のファイルを返すことです。

クライアント側に何かを保存するためのより良い/より高速な方法はありますか? (私はすべてを試してみたいです)?

マニフェスト.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);
});
4

1 に答える 1

5

あなたの質問はSSCCEではないのでテストするのは難しいですが、あなたの問題はJSの非同期性を理解することだと思います.

したがって、コードが実際にどのように実行されるか:

  1. 最初window.webkitRequestFileSystem(PERSISTENT, 0, successCallback, errorHandler);に実行されます
  2. 次にsendResponse({data: theme});、保存されているものを含む応答を送信しますtheme
  3. 次に、ファイル要求の成功に応じて、どちらsuccessCallbackかが呼び出されます。errorHandlersuccessCallback呼び出されると、theme変数に必要な値が入力されます。しかし、あなたはすでに応答を送信しているため、遅くなります。

次にメッセージを渡すと、値を送信した後にのみコードが新しい値を見つけるため、以前のテーマ値 (ポイント 2) を受け取ります。

解決策は、目的の値を見つけた後にsendResponseの内部で呼び出すことです ( に渡す必要があります)。そうする場合は、コードが常に有効な応答を受け取るようにするために、関数に追加することを検討してください。successCallbacksendResponsereadFromFileStoragesendResponseerrorHandler

をコールバックに移動する場合は、関数sendResponseから true を返す必要があります。そうしないと、戻りチャネルが閉じられ、応答が送信されません。addListeneraddListener

于 2013-12-02T16:02:45.220 に答える