Catch Error from gapi.client.load

懵懂的女人 提交于 2019-12-05 13:21:18

Unfortunately, the documentation is pretty useless here and it's not exactly easy to debug the code in question. What gapi.client.load() apparently does is inserting an <iframe> element for each API. That frame then provides the necessary functionality and allows accessing it via postMessage(). From the look of it, the API doesn't attach a load event listener to that frame and rather relies on the frame itself to indicate that it is ready (this will result in the callback being triggered). So the missing error callback is an inherent issue - the API cannot see a failure because no frame will be there to signal it.

From what I can tell, the best thing you can do is attaching your own load event listener to the document (the event will bubble up from the frames) and checking yourself when they load. Warning: While this might work with the current version of the API, it is not guaranteed to continue working in future as the implementation of that API changes. Currently something like this should work:

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);

Just to repeat the warning from above: this code makes lots of assumptions. While these assumptions might stay true for a while with this API, it might also be that Google will change something and this code will stop working. It might even be that Google uses a different approach depending on the browser, I only tested in Firefox.

chaduhduh

I know this is old but I came across this randomly. You can easily test for a fail (at least now).

Here is the code:

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
}

Example

This is an extremely hacky way of doing it, but you could intercept all console messages, check what is being logged, and if it is the error message you care about it, call another function.

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"

An example is here - I log two things, one is the error message, the other is something else. You'll see the first one cause an alert, the second one does not.

http://jsfiddle.net/keG7X/

You probably would have to run the interceptConsole function before including the gapi script as it may make it's own copy of console.

Edit - I use a version of this code myself, but just remembered it's from here, so giving credit where it's due.

I use a setTimeout to manually trigger error if the api hasn't loaded yet:

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);
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!