Unchecked runtime.lastError при использовании API Chrome

Я использую API chrome.fileSystem в своем приложении, чтобы открыть файл. Когда я нажимаю кнопку Cancel в диалоговом окне выбора файла, возникает ошибка:

Отключено runtime.lastError во время работы fileSystem.chooseEntry: Пользователь отменен

Как исправить эту ошибку?

Ответ 1

Эта ошибка не важна в этом случае, но я объясню это и как избавиться от нее.

Что это за ошибка?

API-интерфейсы Chrome в основном асинхронны: у вас есть обратный вызов, который вызывается при завершении операции.

В случае chrome.fileSystem.chooseEntry выбранная запись (или записи) будет передана обратному вызову:

chrome.fileSystem.chooseEntry(
  {/* options */},
  function(entry) {
    // This is the callback for the API call; you can do something with entry
  }
);

Однако API не гарантирует получение результата. Например, как и в вашем случае, пользователь может отказаться предоставить доступ, нажав "Отмена". Тогда нет записи для работы, и вам может понадобиться объяснение, почему это произошло. Как поднять ошибку, не загрязняя все обратные вызовы дополнительным аргументом "ошибка"?

Обычно Chrome использует это, устанавливая глобальную переменную chrome.runtime.lastError во время вызова обратного вызова. Для асинхронных API-интерфейсов Chrome одинаково использовать это вместо аргумента ошибки. Фактически, цитируя chrome.fileSystem docs:

Все сбои уведомляются через chrome.runtime.lastError.

  • Если все будет в порядке, это будет undefined.
  • Если есть проблема, она будет непустой, а chrome.runtime.lastError.message объяснит, что не так.

Однако некоторые обратные вызовы не проверяли эту переменную ошибки. Это может указывать на ошибку программирования, а Chrome добавил проверки, что chrome.runtime.lastError фактически проверяется (оценивается) в обратном вызове. Если нет, он считает это необработанным исключением и выдает эту ошибку.

Почему я говорю, что это не важно?

В то время как это ошибка, она не нарушит выполнение вашей программы (она брошена в конце задачи async), и на самом деле не будет отображаться вашим пользователям.

И хотя я говорю, что это не важно, вы должны проверить логику программы. Это может быть или не быть в порядке - это должно быть (кормовое) предупреждение.

Почему он существует?

Чтобы вы, разработчик, предупреждали, что ваш код , вероятно, пытается использовать результат, которого не существует, потому что что-то пошло не так.

Возможно, вы уже проверяете ошибку, например.

if (entry) {
  // Process entry
} else {
  // Something went wrong (but what?)
}

Chrome не использует сложные эвристики, чтобы узнать, ожидает ли ваш код эту возможность. Как отмечено, ошибки сообщаются через chrome.runtime.lastError, и вы должны проверить его.

Обратите внимание, что эта ошибка возникает только тогда, когда происходит что-то плохое, а не когда вызов API заканчивается нормально.

Могу ли я его поймать?

Не совсем; он не поднимается вашим кодом, а код очистки, который обрабатывает асинхронные задачи в API Chrome; поэтому использование try ... catch в вашем обратном вызове не поможет. Поскольку он асинхронен, использование try вокруг исходного вызова API также не поможет.

Что с ним делать?

Вы должны добавить логику в свой обратный вызов, который проверяет проблемы так, как это ожидает Chrome, и, вероятно, реагирует на него.

function(entry) {
  if(chrome.runtime.lastError) {
    // Something went wrong
    console.warn("Whoops.. " + chrome.runtime.lastError.message);
    // Maybe explain that to the user too?
  } else {
    // No errors, you can use entry
  }
}

Пока Chrome видит, что вы проверили значение при ошибке (т.е. оценили его в своем обратном вызове), ошибка не будет выбрана.

Ответ 2

Поздно к вечеринке, но вот как я подавил ошибку в вызове chrome.windows.remove(), если она помогает кому-то еще. Вместо

chrome.windows.remove(foo);  // unconditional; runtime.lastError not checked

Я использовал

chrome.windows.remove(
        foo,
        function ignore_error() { void chrome.runtime.lastError; }
);

void оценивает свой операнд, а затем возвращает undefined. Я думаю, что этот код достаточно эффективно документирует, что его целью является игнорировать ошибки:).

Для краткости ignore_error() можно вытащить из этого вызова и использовать для множественных вызовов chrome API, или имя ignore_error может быть опущено.

Ответ 3

Для этого типа ошибок try catch не будет полезно. Вместо этого вы можете получить доступ к глобальной переменной chrome.runtime.lastError как @xan, упомянутой в его замечательном ответе выше (кстати, вы должны прочитать ее и перенести ее!).

Теперь я приведу пример, который можно использовать:

function catchLastError(){
  if(chrome.runtime.lastError){
    console.log("error: ", chrome.runtime.lastError);
  }else{
    // some code goes here.
  }
}

chrome.fileSystem.chooseEntry(yourEntry,catchLastError);