Расширение Chrome: хранить данные в фоновом режиме

Я хочу иметь возможность хранить данные в фоновом режиме (в моем расширении), чтобы иметь доступ к этим данным между несколькими доменами.

Где что я делаю:

content-script.js

function setItem(name, data) {
    chrome.extension.sendMessage({ command: 'setItem', name: name, data: data });
}

function getItem(name) {
    chrome.extension.sendMessage({ command: 'getItem', name: name }, function(response) {
        return response;
    });
}

background-script.js

Storage.prototype.setObject = function(key, value) {
    this.setItem(key, JSON.stringify(value));
}

Storage.prototype.getObject = function(key) {
    var value = this.getItem(key);
    return value && JSON.parse(value);
}

chrome.extension.onMessage.addListener(function(request, sender, sendResponse) {
    switch (request.command) {
        case 'setItem':
            localStorage.setObject(request.name, request.data);
            return;
        case 'getItem':
            sendResponse(localStorage.getObject(request.name));
            return;
    }
});

Но безуспешно, так как я не могу вернуться из обратного вызова на getItem.

Я получаю данные внутри обратного вызова function(response) { }, просто не могу вернуть их как результат getItem.

Как мне это сделать?


person Thiago Belem    schedule 28.06.2012    source источник


Ответы (3)


Этот вопрос 2012 года был поднят для актуального ответа. Ну тогда..

Прямо сейчас правильным ответом будет использование chrome.storageAPI. Это API, доступный как для страниц расширения, так и для сценариев контента, и он обеспечивает асинхронное хранилище. Требуется разрешение "storage", но это разрешение не генерирует предупреждений.

// Setting
chrome.storage.local.set({key: data}, function() {
  if(chrome.runtime.lastError) {
    console.error(
      "Error setting " + key + " to " + JSON.stringify(data) +
      ": " + chrome.runtime.lastError.message
    );
  }
});

// Getting
chrome.storage.local.get("key", function(data) {
  // Do something with data.key
});

См. также раздел Примеры документации.

Обратите внимание, что в любом случае (этот подход или фоновый обмен сообщениями) вы не можете создать функцию getData, которая возвращает результат, поскольку вызов является асинхронным.

Некоторые советы и рекомендации:

  1. Вы можете установить или получить сразу несколько значений, передав объект или массив в качестве запроса. Вы можете прочитать все значения, передав запрос null.

  2. Вы можете указать значение по умолчанию для операции get() на случай, если для ключа не сохранено значение, передав запрос типа {key: defaultValue}

  3. Вы можете получать уведомления обо всех изменениях в хранилище с помощью события chrome.storage.onChanged.

  4. chrome.storage.local подчиняется разрешению "unlimitedStorage".

  5. chrome.storage.sync будет распространять это значение на все профили, в которые выполнен вход в одну и ту же учетную запись Google, если для расширений включена синхронизация Chrome. Однако помните об квотах.

  6. Если вам абсолютно необходим синхронный доступ, вы можете подделать его с помощью локального кеша, поддерживаемого chrome.storage. Однако есть ограничения: пока вы находитесь в синхронном блоке кода, ваш кеш не будет обновляться с учетом изменений с других страниц, и вам нужно один раз прочитать значения асинхронно, чтобы заполнить кеш.

person Xan    schedule 22.02.2015
comment
также убедитесь, что вы не используете зарезервированные ключевые слова, такие как «история», при сохранении ваших объектов ... потеряли слишком много времени с этим. - person Claudiu Creanga; 18.02.2016

Content.js

var someVar = "hey hey!";

chrome.extension.sendRequest({method: "fromContentScript",greeting: someVar}, function(response) {

    console.log(response.data); // response back from BG

    if(response.who == 'bg'){ // checks if the response is from BG
            //Something happened ...
    }

    var responseFromBg = response.data; // the response incase we need to use the message sent back... in this case should be 'hey yourself'


});

Фон.js

chrome.extension.onRequest.addListener(function(request, sender, sendResponse) {
  // From content script.
  if (sender.tab) {
    if (request.method == "fromContentScript"){

        localStorage.setItem("welcome-message",request.greeting); // in this case there will now be a localStorage variable called 'welcome-message' set with the value of 'hey hey!'. This will be viewable in the chrome:extensions page, click on the 'background.html / generated background.html' then view the 'Development Tools' or in Windows hit 'CTRL + SHIFT + I' and look at the 'LocalStorage' tab...

      sendResponse({who: "bg",data: "hey yourself"}); // this is the response sent back, 'who' tells the content page where is responding, so it can do something with the response if needed.
        }else{
      sendResponse({}); // snub them.
        }
  }
});

Manifest.json // на всякий случай, если у вас проблема с манифестом... вот большая часть моих..

{
  "name": "Name here",
  "version": "1",
  "manifest_version": 2,
  "description": "Enter desc here.",  
    "browser_action": {
    "default_icon": "img/icon16.png",
    "default_popup": "popup.html"
  },    
    "background": {
    "scripts": ["background.js"]
  },
  "permissions": [
    "tabs", "*://*/*"
  ],
    "icons": { "16": "img/icon16.png",
           "48": "img/icon48.png",
          "128": "img/icon128.png" },
  "content_scripts": [
    {
      "matches": ["*://*/*"],
      "js": ["js/jquery-1.7.2.min.js","content_script.js"],
      "run_at": "document_end"
    }
  ]
}

Я бы использовал ваш пример, но сегодня утром я тороплюсь. Я попытался объяснить все вары как можно подробнее - извините :(

person Chris    schedule 28.06.2012
comment
sendRequest и onRequest устарели - person Thiago Belem; 28.06.2012
comment
@Chris Я пробовал ваш пример, но, к сожалению, не работает, не могли бы вы мне помочь :) - person We're All Mad Here; 12.03.2014
comment
1-й я не знаю, где посмотреть, как я создал database, 2-й я использовал ваши background js и content js, но без помощи - person We're All Mad Here; 12.03.2014
comment
Вам нужно открыть фоновую страницу, используя страницу расширений, затем F12 и просмотреть локальное хранилище на вкладке «Ресурсы». - person Chris; 12.03.2014

background-script.js:

chrome.extension.onMessage.addListener(function(request, sender, sendResponse) {
    switch (request.command) {
        case 'setItem':
            localStorage[request.name] = JSON.stringify(request.data));
            return;
        case 'getItem':
            var retValue;
            if (typeof(localStorage[request.name]) === 'string') {
                retValue = JSON.parse(localStorage[request.name]);
            }
            sendResponse(retValue);
            return;
        case 'deleteItem':
            if (typeof localStorage[request.name] !== 'undefined') {
                delete localStorage[request.name];
            }
            return;
    }
});

Если ключа нет в localStorage, getItem вернет undefined. Вместо того, чтобы определять функцию getItem так, как вы это сделали, вы должны отправить сообщение в фоновый режим с обратным вызовом, а затем сделать что-то со значением при вызове обратного вызова. Вы не можете вернуть значение из функции getItem, но можете использовать это значение в обратном вызове при его вызове:

function getItem(name, callback) {
    chrome.extension.sendMessage({command: 'getItem', name: name}, function(response) {
        if (typeof(callback) === "function") {
            callback(response);
        }
    });
}
person Uri    schedule 23.02.2015