#javascript #google-cloud-endpoints
#javascript #google-облако-конечные точки
Вопрос:
Я использую Google App Engine с конечными точками Java и Google Cloud. В моем интерфейсе JavaScript я использую этот код для обработки инициализации, как рекомендовано:
var apisToLoad = 2;
var url = '//' $window.location.host '/_ah/api';
gapi.client.load('sd', 'v1', handleLoad, url);
gapi.client.load('oauth2', 'v2', handleLoad);
function handleLoad() {
// this only executes once,
if (--apisToLoad === 0) {
// so this is not executed
}
}
Как я могу обнаружить и обработать, когда gapi.client.load
происходит сбой? В настоящее время я получаю сообщение об ошибке, напечатанное на консоли JavaScript, в котором говорится: Could not fetch URL: https://webapis-discovery.appspot.com/_ah/api/static/proxy.html)
. Возможно, это моя ошибка, или, может быть, это временная проблема со стороны Google — прямо сейчас это не моя забота. Я пытаюсь воспользоваться этой возможностью, чтобы хорошо обрабатывать такие ошибки на стороне клиента.
Итак, как я могу с этим справиться? handleLoad
не выполняется для вызова, который выдает ошибку, gapi.client.load
похоже, что у него нет отдельного обратного вызова с ошибкой (см. Документацию), на самом деле он не выдает ошибку (только выводит ее на консоль), и он ничего не возвращает. Чего я не понимаю? Моя единственная идея на данный момент — установить тайм-аут и предположить, что произошла ошибка, если инициализация не завершается через X секунд, но это явно не идеально.
Редактировать:
Эта проблема возникла снова, на этот раз с сообщением ERR_CONNECTION_TIMED_OUT
при попытке загрузить oauth
материал (что определенно находится вне моего контроля). Опять же, я не пытаюсь исправить ошибку, это просто подтверждает, что ее стоит обнаружить и корректно обработать.
Ответ №1:
Я знаю, что это старое, но я случайно наткнулся на это. Вы можете легко проверить сбой (по крайней мере, сейчас).
Вот код:
gapi.client.init({}).then(() => {
gapi.client.load('some-api', "v1", (err) => { callback(err) }, "https://someapi.appspot.com/_ah/api");
}, err, err);
function callback(loadErr) {
if (loadErr) { err(loadErr); return; }
// success code here
}
function err(err){
console.log('Error: ', err);
// fail code here
}
Комментарии:
1. Спасибо за ответ. Я больше не использую эту библиотеку, но я рад видеть, что они внесли улучшения!
Ответ №2:
К сожалению, документация здесь довольно бесполезна, и отладить рассматриваемый код не совсем просто. Что gapi.client.load()
, по-видимому, делает, так это вставляет <iframe>
элемент для каждого API. Затем этот фрейм предоставляет необходимую функциональность и позволяет получить к ней доступ через postMessage()
. Судя по всему, API не прикрепляет load
прослушиватель событий к этому фрейму и скорее полагается на сам фрейм, чтобы указать, что он готов (это приведет к запуску обратного вызова). Таким образом, обратный вызов с отсутствующей ошибкой является неотъемлемой проблемой — API не может увидеть сбой, потому что не будет фрейма, который бы сигнализировал об этом.
Из того, что я могу сказать, лучшее, что вы можете сделать, это прикрепить свой собственный load
прослушиватель событий к документу (событие будет всплывать из фреймов) и проверять себя при их загрузке. Предупреждение: Хотя это может работать с текущей версией API, не гарантируется продолжение работы в будущем по мере изменения реализации этого API. В настоящее время что-то вроде этого должно работать:
var framesToLoad = apisToLoad;
document.addEventListener("load", function(event)
{
if (event.target.localName == "iframe")
{
framesToLoad--;
if (framesToLoad == 0)
{
// Allow any outstanding synchronous actions to execute, just in case
window.setTimeout(function()
{
if (apisToLoad > 0)
alert("All frames are done but not all APIs loaded - error?");
}, 0);
}
}
}, true);
Просто чтобы повторить предупреждение выше: этот код делает много предположений. Хотя эти предположения могут оставаться верными некоторое время с этим API, также может случиться так, что Google что-то изменит, и этот код перестанет работать. Возможно даже, что Google использует другой подход в зависимости от браузера, я тестировал только в Firefox.
Комментарии:
1. Спасибо за ваше исследование и четкое представление о недостатках этого метода. Учитывая эти недостатки, я могу решить, что просто подождать 20 секунд, предполагая ошибку, является лучшим решением, но я определенно сначала попробую это в любом случае.
Ответ №3:
Это чрезвычайно хакерский способ сделать это, но вы могли бы перехватывать все console
сообщения, проверять, что регистрируется, и, если это сообщение об ошибке, которое вас волнует, вызвать другую функцию.
function interceptConsole(){
var errorMessage = 'Could not fetch URL: https://webapis-discovery.appspot.com/_ah/api/static/proxy.html';
var console = window.console
if (!console) return;
function intercept(method){
var original = console[method];
console[method] = function() {
if (arguments[0] == errorMessage) {
alert("Error Occured");
}
if (original.apply){
original.apply(console, arguments)
}
else {
//IE
var message = Array.prototype.slice.apply(arguments).join(' ');
original(message)
}
}
}
var methods = ['log', 'warn', 'error']
for (var i = 0; i < methods.length; i )
intercept(methods[i])
}
interceptConsole();
console.log('Could not fetch URL: https://webapis-discovery.appspot.com/_ah/api/static/proxy.html');
//alerts "Error Occured", then logs the message
console.log('Found it');
//just logs "Found It"
Пример здесь — я регистрирую две вещи, одна из которых — сообщение об ошибке, другая — что-то еще. Вы увидите, что первая ошибка вызывает предупреждение, вторая — нет.
Вероятно, вам пришлось бы запустить interceptConsole
функцию перед включением gapi
скрипта, поскольку он может создать собственную копию консоли.
Редактировать — я сам использую версию этого кода, но просто вспомнил, что она из here, поэтому отдаю должное тому, что должно.
Комментарии:
1. Это будет работать только для
console.log()
вызовов, инициированных JavaScript-кодом страницы. В этом случае сообщение об ошибке, похоже, исходит из браузера и не будет перехвачено.2. Спасибо, что нашли время ответить и предоставить образец. Проблема: я не знаю, какие возможные сообщения об ошибках
gapi
могут возникнуть.
Ответ №4:
Я использую setTimeout, чтобы вручную вызвать ошибку, если api еще не загружен:
console.log(TAG 'api loading...');
let timer = setTimeout(() => {
// Handle error
reject('timeout');
console.error(TAG 'api loading error: timeout');
}, 1000); // time till timeout
let callback = () => {
clearTimeout(timer);
// api has loaded, continue your work
console.log(TAG 'api loaded');
resolve(gapi.client.apiName);
};
gapi.client.load('apiName', 'v1', callback, apiRootUrl);