2017-01-18 5 views
4

J'ai eu du mal à écrire du code qui fera une demande POST de manière fiable à la fermeture de la fenêtre de l'onglet. Navigator.sendBeacon semble être exactement ce dont j'ai besoin (je ne demande que cela fonctionne pour Google Chrome).Appel d'une requête POST pour la journalisation à partir de la fenêtre de déchargement

$(global).bind('unload', function() { 
    let body = { 
    UserEmail: appState.user.email, 
    Job: { 
     Id: appState.jobId 
    }, 
    Timestamp: '/Date(' + new Date().getTime() + ')/', 
    EventOrigin: 'PdfReviewClient', 
    Event: 'JobClosed' 
    }; 
    let headers = { 
    Authorization: `JWT ${authenticationState.token}`, 
    'Content-Type': 'application/json; charset=utf8' 
    }; 
    let blob = new Blob([JSON.stringify(body)], headers); 
    navigator.sendBeacon(configuration.rootApiUrl + 'jobevents', blob); 
}); 

Ma balise inclut des en-têtes personnalisés, c'est pourquoi je crée un blob.

Cependant, cette demande ne semble pas se produire. Ceci est particulièrement difficile à déboguer puisque la fenêtre se ferme. Donc, la question est, pourquoi ma balise n'envoie pas?

+0

Je suppose que vous avez vérifié que la demande se produit lorsque * not * n'est pas fait à la fermeture du navigateur? – Jorg

+0

@Jorg Oui, j'ai. Bonne pensée, merci de vérifier, mais ce n'est pas le problème dans ce cas. –

+0

Et le déchargement se déclenche lui aussi? Vous pourriez être en mesure de le tester avec un 'alert' pour voir s'il bloque la fermeture de la fenêtre – Jorg

Répondre

3

La question était la seule tête que vous pouvez définir avec navigator.sendBeacon est Content-Type, et que vous définissez que par la mise en type dans les options de Blob. La route du serveur a dû être modifiée pour accueillir la requête sans en-tête Authorization (je l'ai passée comme paramètre d'URL à la place - bizarre pour une requête POST, mais apparemment la seule façon de le faire avec une balise). Voici comment il avait l'air à la fin:

$(global).bind('unload', function() { 
    if(appState.jobId == null) return; 

    let headers = { 
    type: 'application/json' 
    }; 

    let jobEventLoggingBody = { 
    UserEmail: appState.user.email, 
    Job: { 
     Id: appState.jobId 
    }, 
    Timestamp: '/Date(' + new Date().getTime() + ')/', 
    EventOrigin: 'PdfReviewClient', 
    Event: 'JobClosed' 
    }; 
    let jobEventLoggingUrl = `${configuration.rootApiUrl}jobevents?jwt=${authenticationState.token}`; 
    let jobEventLoggingBlob = new Blob([JSON.stringify(jobEventLoggingBody)], headers); 
    navigator.sendBeacon(jobEventLoggingUrl, jobEventLoggingBlob); 
}); 

Voir aussi this question qui traite spécifiquement de l'envoi d'en-têtes dans les balises.

+0

J'ai rencontré le même problème - je devais envoyer les données sous la forme d'une chaîne de requête. Merci pour le q + a. Tout le monde sait pourquoi (puisque la chaîne de requête est généralement pour GET, et puisque sendBeacon est une requête POST, je m'attendais à ce que les valeurs que j'envoie soient dans le corps). – xenetics

0

Je ne sais pas si cela pourrait vous aider. Vous pouvez utiliser ceci pour déboguer.

function logData() { 
    var newWindow = window.open(); 
    newWindow.document.write("ohai"); 
} 

window.addEventListener("unload", logData, false);