开发者

Chrome extension message passing, when xhr call fails in jQuery

I'm building an extension in Google Chrome that issues queries against websites.

The queries are issued by the "background page" on request from the "content script"; when the background page receives a request to issue a query, it sends the query out, parses the response and sends the response back to the content script, using sendResponse().

It all works fine when using XMLHttpRequest(); but开发者_StackOverflow社区 my problem is that if I want to issue queries using jQuery .get() or .load(), then when the queries fail, they fail silently and the response is never sent to the content script.

If I register an event handler with .ajaxError() the error is catched, but from this event handler I apparently cannot call sendResponse() because I get the following Chrome error:

"Attempting to use a disconnected port object"

Searching for this error only retrieves the source code for Chrome where this text is found, so it's not very helpful.

In short, my question is: is it possible to use jQuery.get() in a background script of a Chrome extension, and still be able to send a response to the content script when the request fails? (and if yes, how)


This is hard to address directly without a code sample (how were you passing sendResponse to the error handler?), but I think there are some alternatives to building the XHR yourself.

  • Respond asynchronously: you could send an empty response immediately to the content script and then later initiate a new connection to the content script to send the response. The content script will need to add a listener for messages. Obviously if you're making multiple of these requests you'll want some token to be passed back and forth so that you can match up responses to their original requests.
  • Use $.ajax(): this allows you to specify both a success and an error callback inline; if you can successfully sendResponse from the success callback, you should also be able to from the error callback.
  • Create a long-living port: long-living connections let you post a message to the content script at any time.

I'd also like to think that you could call sendResponse from a completely separate function if you stored the sendResponse function so that it was accessible to the error handler, but maybe you've proven that false already (would love to have seen your code). The documentation makes it sound like the request is open until it's responded to.


After looking at the code to see if I could extract some of it to build a working example (in response to serg comment), I don't think what I want to do is possible with jQuery.

In jQuery, when an ajax call fails, an error event is called (for it to be caught by the .ajaxError() event handler), and then the function ends / returns. When the .ajaxError() handler runs, the function is therefore dead. (That, I believe, is the whole point of the asynchronous event system in JS).

Now, I'm only guessing here, but I think that in Chrome, the communication channel between the content script and the background script is closed when the listener function has run; one cannot send a response from the background script to the content script after the end of the listener function, which is what I was trying to do when handling the ajax error in an event handler.

So, what I ended up doing was re-implement an ajax function that actually sends back a complete object: if the call fails, it returns the fact that there has been an error, together with the error code, so that the caller function (actually a callback) can deal with it and send back a response to the content script.

It's only a few lines, and (I think) quite generic, so here it is:

function xhr(url, callback) {
    var req = new XMLHttpRequest();
    req.open("GET", url, true);
    req.onreadystatechange = function() {
        if (req.readyState == 4) {
            var resp = {
                "url": url,
                "status": req.status
                };
            if (req.status == 200) {
                resp.html = req.responseText;
                resp.outcome = "ok";
                }
            else {
                resp.outcome = "error";
                }
            callback(resp);
            }
        }
    req.send(null);
    }
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜