Webkit (Chrome или Safari) способ безопасного выполнения AJAX в onunload / onbeforeunload - PullRequest
0 голосов
/ 14 декабря 2011

В моих тестах Chrome (и, наверное, как и любой другой браузер webkit) не в состоянии выполнить AJAX-запрос ДО выхода из страницы.

Представьте, например, что вам нужно что-то почистить на серверепотому что пользователь нажал на какую-то ссылку или покинул страницу.

Первое, что я заметил, это то, что window.onunload НЕ работает в Chrome (Webkit?)

Как только вы используете window.onbeforeunloadУБЕДИТЕСЬ, что не помещайте в тело вот так: Потому что оно игнорируется.ВЫ ДОЛЖНЫ сделать window.onbeforeunload = function () {...}, чтобы убедиться, что привязка выполнена (или использовать для этого библиотеки jquery или прототипа)

В вашем коде onbeforeunload - АСИНХРОННЫЙ Ajax, подобный этому, НЕ ВЫИГРАЛT работает либо:

var req = new XMLHttpRequest();
req.open("GET", "dosomething.page");
req.send(null);

(хотя это будет работать в Firefox)

Это будет работать, если ТОЛЬКО, если запрос сделан СИНХРОННО, как это:

var req = new XMLHttpRequest();
req.open("GET", "dosomething.page",false);
req.send(null);

Хотя имейте в виду, что синхронизация может привести к зависанию браузера на 2 минуты, если сервер НЕ отвечает.

Кроме того, Firefox, похоже, не работает с onunload.

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

Я не смог правильно протестировать IE на этом.Кто-нибудь знает?IE больше похож на Chrome или FF в этом?или они тоже разные?

1 Ответ

0 голосов
/ 15 декабря 2011

IE, кажется, работает так же, как Firefox (Gecko) в данном конкретном случае:

С помощью этого кода вы можете заставить его работать для WebKit, Firefox и IE:

// Browser detection
var Browser={
    IE:     !!(window.attachEvent && !window.opera),
    Opera:  !!window.opera,
    WebKit: navigator.userAgent.indexOf('AppleWebKit/') > -1,
    Gecko:  navigator.userAgent.indexOf('Gecko') > -1 && navigator.userAgent.indexOf('KHTML') == -1,
    MobileSafari: !!navigator.userAgent.match(/Apple.*Mobile.*Safari/)
};

// Ensures the Ajax Get is performed... Asynchronously if possible 
// or Synchronously in WebKit Browsers (otherwise it'll most probably fail)
function ensureAJAXGet(url, args) {
    var async=!Browser.WebKit;
    var finalUrl=url;
    var sep="";
    for (var key in args) {
        sep=(sep=="?")?"&":"?";
    finalUrl=finalUrl+sep+encodeURIComponent(key)+"="+encodeURIComponent(args[key]);
    }
    var req = new XMLHttpRequest();
    req.open("GET", finalUrl,async);
    req.send();
    return req;
}

// Sets up an unload function for all browsers to work (onunload or onbeforeunload)
function onUnload(func) {
    if(Browser.WebKit) {
        window.onbeforeunload=func;     
    } else {
        window.onunload=func;
    }
}

Тестhtml может быть таким:

var browser="?"
if (Browser.IE) {
    browser="IE";
} else if (Browser.Opera) {
    browser="Opera";
} else if (Browser.WebKit) {
    browser="WebKit";
} else if (Browser.Gecko) {
    browser="Gecko";
} else if (Browser.MobileSafari) {
    browser="MobileSafari"; 
}

function unload() {
    ensureAJAXGet("testajax.jsp", {"browser": browser});
}

onUnload(function() { unload(); });

То есть:

  1. Чтобы сделать что-то с помощью onunload, вы вызываете onUnload () вместо непосредственного использования либо window.onload, либо window.onunload.Это гарантирует, что используется правильное событие (onbeforeunload в WebKit и onunload для остальных)
  2. Чтобы отправить некоторый GET Ajax в функции выгрузки, используйте sureAjaxGet (), который будет асинхронным AJAX, когда это возможно, и синхронным при необходимости (WebKit)
...