0

Je continue à obtenir cette erreur:service erreur de travailleur: événement a déjà répondu à

Uncaught (in promise) DOMException: Failed to execute 'respondWith' on 'FetchEvent': The event has already been responded to.

Je sais que les travailleurs de services répondent automatiquement si des choses asynchrone passe au sein de la fonction de récupération, mais je ne peux pas travailler tout à fait qui le bit serait le délinquant dans ce code:

importScripts('cache-polyfill.js'); 

self.addEventListener('fetch', function(event) { 

    var location = self.location; 

    console.log("loc", location) 

    self.clients.matchAll({includeUncontrolled: true}).then(clients => { 
    for (const client of clients) { 
     const clientUrl = new URL(client.url); 
     console.log("SO", clientUrl); 
     if(clientUrl.searchParams.get("url") != undefined && clientUrl.searchParams.get("url") != '') { 
     location = client.url; 
     } 
    } 

    console.log("loc2", location) 

    var url = new URL(location).searchParams.get('url').toString(); 

    console.log(event.request.hostname); 
    var toRequest = event.request.url; 
    console.log("Req:", toRequest); 

    var parser2 = new URL(location); 
    var parser3 = new URL(url); 

    var parser = new URL(toRequest); 

    console.log("if",parser.host,parser2.host,parser.host === parser2.host); 
    if(parser.host === parser2.host) { 
    toRequest = toRequest.replace('https://booligoosh.github.io',parser3.protocol + '//' + parser3.host); 
    console.log("ifdone",toRequest); 
    } 

    console.log("toRequest:",toRequest); 

    event.respondWith(httpGet('https://cors-anywhere.herokuapp.com/' + toRequest)); 
    }); 
}); 

function httpGet(theUrl) { 
    /*var xmlHttp = new XMLHttpRequest(); 
    xmlHttp.open("GET", theUrl, false); // false for synchronous request 
    xmlHttp.send(null); 
    return xmlHttp.responseText;*/ 
    return(fetch(theUrl)); 
} 

Toute aide serait appréciée.

Répondre

2

Le problème est que votre appel à event.respondWith() se trouve dans la clause .then() de votre promesse de niveau supérieur, ce qui signifie qu'il sera exécuté de manière asynchrone après la résolution du niveau supérieur. Pour obtenir le comportement que vous attendez, event.respondWith() doit être exécuté de façon synchrone dans le cadre de l'exécution du gestionnaire d'événements fetch.

La logique à l'intérieur de votre promesse est un peu difficile à suivre, donc je ne sais pas exactement ce que vous essayez d'accomplir, mais en général vous pouvez suivre ce modèle:

self.addEventListerner('fetch', event => { 
    // Perform any synchronous checks to see whether you want to respond. 
    // E.g., check the value of event.request.url. 
    if (event.request.url.includes('something')) { 
    const promiseChain = doSomethingAsync() 
     .then(() => doSomethingAsyncThatReturnsAURL()) 
     .then(someUrl => fetch(someUrl)); 
     // Instead of fetch(), you could have called caches.match(), 
     // or anything else that returns a promise for a Response. 

    // Synchronously call event.respondWith(), passing in the 
    // async promise chain. 
    event.respondWith(promiseChain); 
    } 
}); 

C'est la idée générale. (Le code semble encore plus propre si vous finissez par remplacer les promesses par async/await.)