Brave ne déclenche pas beforeinstallprompt.

WRInaute accro
Bonjour

Sous Linux Fedora 41 :

Brave ne déclenche pas l'event beforeinstallprompt.

Voici le message d'erreur de Brave à propos de mon manifest.json, et le manifest :


JSON:
    Richer PWA Install UI won't be available on desktop. Please add at least one screenshot with the form_factor set to wide.

    Richer PWA Install UI won't be available on mobile. Please add at least one screenshot with the form_factor set to wide.


    "lang": "fr",
    "default_locale": "fr",
    "manifest_version": 2,
    "version": "0.1.1.2",
    "id": "pronoscourseschevaux", 
    "name": "PWA Pronostics Courses Chevaux",
    "short_name": "Pronostics Courses",
    "description": "Une application élaborée fournissant des pronostics et statistiquues sur les Courses de Chevaux",
    "start_url": "http://localhost/index.html",
    "orientation": "any",
    "background_color": "#2f3d58",
    "theme_color": "#2f3d58",
    "display_override": ["fullscreen", "minimal-ui"],
    "display": "standalone",
    "icons": [
        {
            "src": "/icons/PNG/logo-72x72.png",
            "type": "image/png",
            "sizes": "72x72"
        },
        {
            "src": "/icons/PNG/logo-96x96.png",
            "type": "image/png",
            "sizes": "96x96"
        },
        {
            "src": "/icons/PNG/logo-144x144.png",
            "type": "image/png",
            "sizes": "144x144"
        },
        {
            "src": "/icons/PNG/logo-192x192.png",
            "type": "image/png",
            "sizes": "192x192"
        },
        {
            "src": "/icons/PNG/logo-256x256.png",
            "type": "image/png",
            "sizes": "256x256"
        },
        {
            "src": "/icons/PNG/logo-512x512.png",
            "type": "image/png",
            "sizes": "512x512"
        }
    ]
}


Comment adapter manifest.json pour que le message d'erreur disparaisse ?

Merci beaucoup.

Lighthouse de Brave indique qu'il n'y a aucun contenu, ce qui est vrai car je n'ai pas encore placé les éléments de la PWA.
 
WRInaute accro
Bonjour rick38

C'était une erreur de copie.

J'ai rajouté dans le manifest.json les screenshots avec form_factor à narrow et wide.

320x320 narrow et 512x512 wide.

Les messages du haut ont disparu.

Après arrêt d'autres services workers dans la console de développement, et quelques simplifications dans le javascript, çà s'est mis à marcher, puis rebelote.

Je suis en train de vérifier.

Y a-t-il une condition de timing de navigation de 30s comme aux débuts ?

Merci beaucoup rick38.
 
WRInaute accro
Voilà voilà

Cà marche , mais j'ai dû installer la PWA manuellement d'abord.

C'est probablement un petit bug de Brave.

Je vais me mettre à la programmation de la PWA.

Merci beaucoup rick38. ;)
 
WRInaute accro
Une question.

Comment afficher la page par défaut, précisément quand la PWA est déclenchée ?

Y a-t-il un event Javascript ( dans le html , pas le service worker ) qui spécifie le déclenchement de la PWA ?

Merci beaucoup.
 
WRInaute accro
Plus exactement.

Quels seraient les event Javascript déclenchés quand la PWA est disponible ?

Ou bien quels codes Javascript serviraient d'avis de "start" à la PWA, après que celle-ci ait été installée ?

Et aussi "start" de la PWA lors de lancement ultérieurs ( autres sessions du navigateur ).

Je peux fournir mon implémentation ( partielle ou complète ) si vous voulez.

Cà marche sous Brave.

Merci beaucoup de votre aide.
 
WRInaute accro
Excusez-moi Spout.


JavaScript:
const INST    = 'Inst';

const IOS    = 'iOS';

const SAMSUNG    = 'Samsung';

const FIREFOX    = 'Firefox';

const MOBILE    = ' MOBILE';

const OTHERS    = 'Others';

const NOTINST    = 'NotInst';

const APP = {
    // Declare the deferredPrompt variable in the global scope
    deferredPrompt : null,
    installButton : document.getElementById("install"),
    init() {
        if ("serviceWorker" in navigator) {
            // Registering Service Worker
            navigator.serviceWorker.register('/SW.js', { scope: '/' })
                .then(function(registration) {
                    console.log("Service worker registered with scope: " + registration.scope);
                }).catch(function(err) {
                    console.log("Service worker failed: " + err);
                });
            if ('BeforeInstallPromptEvent' in window) {
                window.addEventListener('beforeinstallprompt', (e) => {
                    // Prevent Chrome 67 and earlier from automatically showing the prompt
                    e.preventDefault();
                    APP.deferredPrompt = e;
                });
                APP.installButton.addEventListener("click", async () => {
                    if (APP.deferredPrompt) {
                        const result = await APP.deferredPrompt.prompt();
                        console.log(`Install prompt was: ${result.outcome}`);
                        APP.installButton.style.display = 'none';
                    } else if (window.matchMedia('(display-mode: standalone)').matches) {

                        // hide our user interface that shows our A2HS button
                        APP.installButton.style.display = 'none';

                        // The app is already installed
                        console.log('You have already installed the app.');
                    } else {
                        // hide our user interface that shows our A2HS button
                        APP.installButton.style.display = 'none';

                        console.log('Erreur : BeforeInstallPromptEvent event is null.');

                        // The app is uninstalled
                        APP.deferredPrompt = null; // Reset the APP.deferredPrompt variable
                    }
                });
            } else {

                // hide our user interface that shows our A2HS button
                APP.installButton.style.display = 'none';

                var isMobile = {
                    Mob: function () {
                        return navigator.userAgent.match(/Mob/);
                    },
                    Android: function () {
                        return navigator.userAgent.match(/Android/i);
                    },
                    Symbian: function () {
                        return navigator.userAgent.match(/symb/i);
                    },
                    Firefox: function () {
                        return navigator.userAgent.match(/Firefox\/\d+/i);
                    },
                    BlackBerry: function () {
                        return navigator.userAgent.match(/BlackBerry/i);
                    },
                    iOS: function () {
                        return navigator.userAgent.match(/iPhone|iPad|iPod/i);
                    },
                    Opera: function () {
                        return navigator.userAgent.match(/Opera Mini/i);
                    },
                    Samsung: function () {
                        return navigator.userAgent.match(/SAMSUNG|Samsung|SGH-[I|N|T]|GT-[I|N]|SM-[A|N|P|T|Z]|SHV-E|SCH-[I|J|R|S]|SPH-L/i);
                    },
                    Windows: function () {
                        return (
                            navigator.userAgent.match(/IEMobile/i) ||
                            navigator.userAgent.match(/WPDesktop/i)
                        );
                    }
                };

                var type    = NOTINST;

                var heading    = "Pour installer la PWA :<br>*********************<br>";
                var message    = '';

                if(isMobile.Firefox) {

                    if(isMobile.Mob()) {

                        type = FIREFOX + MOBILE;

                        message = "Cliquez l'option \"Install\" ou \"Install App\"<br>" + " à côté de la barre d'adresse du haut,<br>" + " puis \"Ajouter à l'écran d'accueil\".";
                    } else {

                        type = FIREFOX;

                        heading = "";

                        message = "Votre navigateur ne supporte pas les PWA.";
                    }
                } else {

                    if(isMobile.iOS) {

                        type = IOS;

                        message = "Cliquez sur l'icône <img src=\"/UI/fleche.jpg\" />.<br>" + "Sélectionnez \"Ajouter à l'écran d'accueil\" dans le menu.<br>" + "Appuyez sur \"Ajouter\" en haut à droite.";

                    } else if(isMobile.Samsung) {

                        type = SAMSUNG;

                        message = "Cliquez l'icône \"Install\" sur la barre d'adresse du haut,<br>" + " ou sur \"Menu\" sur la barre du bas<br>" + " puis \"Ajouter à l'écran d'accueil\".";

                    } else {

                        type = OTHERS;

                        message = "Cliquez sur le menu sur la barre du haut/bas<br>" + " puis \"Ajouter à l'écran d'accueil\".";
                    }
                }

                const invite = document.createElement('h1');

                invite.classList.add("message");

                invite.innerHTML = heading;

                const dialog = document.createElement('div');

                dialog.classList.add("invite");

                dialog.innerHTML = message;

                invite.append(dialog);

                document.body.append(invite);
            }
        } else {

            APP.installButton.style.display = 'none';

            const invite = document.createElement('h1');

            invite.classList.add("message");

            invite.innerHTML = 'Votre navigateur ne supporte pas les PWA';

            document.body.append(invite);
        }
    }
};

document.addEventListener('DOMContentLoaded', APP.init);


Ma question est :

Où est-ce que je met le code pour commencer à afficher les pages de la pwa ?

app.js est lancé dans le index.html

Merci.
 
WRInaute accro
Pardon

La fonction init() est lancée quand le DOM est chargé.

Il faudrait que cette fonction init() soit terminée juste avant le début des affichages de la pwa.

Donc, au lieu de :

JavaScript:
document.addEventListener('DOMContentLoaded', APP.init);

A l"intérieur de APP. :

JavaScript:
run() {
    {
        APP.init();
        APP.affic();
    }
}


Et puis :

document.addEventListener('DOMContentLoaded', APP.run);

Cà marche pour init() et affic() lancées séquentiellement, ou le fait que init() soit asynchrone fout le souk ?

Sinon, en mode asynchrone, après quel event ?

Merci beaucoup.
 
WRInaute accro
Beurk.

Event "resize" de window, et puis test sur matchMedia('display-mode : standalone');

Y a-t-il un moyen de lire le display-mode en javascript ?
 
WRInaute accro
Voilà c'est fait.

Je calcule le display-mode en testant les windows.matchMedia('display-mode: ' + media[\i]) de i = 0 à i = media[media.length - 1].

Cà marche, çà déclenche la fonction start() juste après l'install, ou après.

Reste à détecter les install manuelles.

Cà je sais pas faire.
 
WRInaute accro
Pour tester le cas des navigateurs à install non automatique.

Je suis sous Fedora 41.

Quels navigateurs supportant les PWA mais pas l'event beforeinstallprompt ?

Merci beaucoup.
 
WRInaute accro
Excusez-moi spout

Le problème n'est pas de détecter les browser supportant ( ou non ) l'event beforeinstallprompt, mais bien de détecter l'installation déjà faite de PWA sous des browsers ne supportant pas cet event.

Donc, install manuelle.

Merci beaucoup de ton aide.
 
WRInaute accro
Oui spout

L'API que tu indiques, est valide sous Android Chrome 80+ et Windows.

Il me semble que Chrome version 80 supporte l'event beforeinstallprompt et l'install automatique par prompt().


Détecter display-mode: avec matchMedia() pourrait-t-il être inclus dans un traitement d'event, et quel event ?

Le changement de display-mode correspond à quel event ?

Merci beaucoup de ton aide.
 
WRInaute accro
Bonjour

MutationObserver permet-il de détecter les modifications de display:mode lues par matchMedia() ?

A quel objet du DOM s'applique display:mode ?

Est-ce à l'objet window ?

Dans ce cas, quel lien entre l'objet window et display:mode ?

matchMedia() mesure quel objet ?

Merci beaucoup.
 
WRInaute accro
J'ai trouvé.

Merci de corriger.


JavaScript:
const mode = window.matchMedia("(display:mode: standalone)");

function screenTest(e) {

        const MEDIA = ['fullscreen', 'standalone', 'minimal-ui', 'picture-in-picture', 'window-controls-overlay', 'browser'];

        for(var i = 0; i < MEDIA.length; i++) {
            if(window.matchMedia('(display-mode: ' + MEDIA[i]).matches) {
                break;
            }
        }

        if(i < MEDIA.length) {
            APP.Media = MEDIA[i];
        } else {
            APP.Media = null;
        }
    }

mode.addEventListener("change", screenTest);
 
WRInaute accro
Voilà voilà

Il semblerait que çà marche :

JavaScript:
                var mode = window.matchMedia("(display-mode: browser)");

                APP.screenTest();

                mode.addEventListener("change", APP.screenTest);

    screenTest(e) {

         const MEDIA = ['fullscreen', 'standalone', 'minimal-ui', 'picture-in-picture', 'window-controls-overlay', 'browser'];

        for(var i = 0; i < MEDIA.length; i++) {

            console.log('display-mode = ' + MEDIA[i]);

            if(window.matchMedia('(display-mode: ' + MEDIA[i] + ')').matches) {

                break;
            }
        }

        if(i < MEDIA.length) {

            APP.Media = MEDIA[i];

            console.log('display-mode = ' + APP.Media);

            if(APP.Media != 'browser') {

                APP.isStarted = true;

                APP.start();

                return;
            }
        }

        console.log("PWA start failed.");
    },
 
Dernière édition:
WRInaute accro
Bonjour à tous.

Avant de me lancer dans le codage de cette pwa :

Je sais que l'appel au service worker ne doit se faire que sur une seule page, ( page d'accueil ).

Que se passe-t-il si le visiteur a désinstallé la pwa, et qu'après il va directement sur une autre page que celle sur laquelle est le sw ?

Faut que je détecte si la PWA est installée, sinon => page d'accueil ?

Merci beaucoup de votre aide.
 
WRInaute accro
Bonjour

Pour les datas, voici les fichiers produits :

J'ai fait :
***********

tmp_liste_today.json

tmp_liste_tomorrow.json

tmp_liste_old.json

tmp_pronos_today.json

tmp_pronos_tomorrow.json

tmp_pronos_old.json

Reste à faire :
***************

tmp_contact.json

tmp_index.json => page d'accueil

tmp_old.json => liste des courses 10 derniers jours,

tmp_methode.json
 
WRInaute accro
J'ai une question de newbie en pwa :

Mettons un service worker prenant en charge les requêtes fetch lancées par le html.

Ma question est : S'il y a une requête fetch en javascript en dehors du service worker, son exécution sera--elle traitée par le sw ?

Sinon, est-on obligé de cliquer sur des boutons/autres type html pour que le sw traite la requête ?

Merci beaucoup.
 
WRInaute accro
Pardon.

Par "en dehors du service worker" je voulais dire : fetch en Javascript dans un script situé dans le path déclaré par le service worker, éventuellement le même script ou le sw est lancé.

Merci beaucoup.
 
WRInaute accro
Bonjour

J'ai une bonne nouvelle :

Ma PWA fonctionne bien en localhost.

Pour l'instant j'ai toutes les pages de mon site, sauf index.php ( la page d'accueil ), la page de contact, et la page d'utilisation de mon site.

J'ai testé celà ce matin sur Brave sous Linux Fedora 41.

Pfffouu... comme dirait Gaston Lagaffe.

La mise au point a duré longtemps.

J'avais un problème de Promise.

Voilà.
 
WRInaute accro
Hé bé

Les données lues sont des templates et des data ( pour le render() de Mustache ).

Ces datas devraient être de type text/plain.

Maintenant j'ai des content-type octet-stream au lieu de text/hml ou text/plain.

Le résultat n'est pas une string.

J'ai envisagé des solutions complexes pour traduire à la volée les octet-stream en string.

Est-ce qu'il suffit de passer à la moulinette str.toString() ?

Merci beaucoup.
 
WRInaute accro
Bon bon

Je vais faire une class de connexion fetch et autres Javascript tout azimut, prenant en compte les unlocks des responses.body.

Amicalement.
 
WRInaute accro
Errare Humanum est.

Pas besoin de class tout azimut.

Mes fonctions d'interface réseau gèrent les text/plain/html/css/csv et autres, plus les application/octet-stream et json.

Il n'y a plus de blocage de response.

Cà roule, plus qu'à terminer les templates et les data.

Comme dirait Spout : "Late but no least".

Cà boume.
 
WRInaute accro
Bah.

Petite question probablement stupide :

La fonction render() de Mustache rend un texte pur et et est déclenchée dans le sw.

Je sais ( grâce à Bing IA ) comment l'envelopper dans une promise.

Comment traduire le texte en Response pour que le script en dehors du sw, puisse le lire ?

Ou, en général : comment convertir un texte pur en Response ?

Merci beaucoup.
 
WRInaute accro
Bonjour

Question sur laquelle je sèche :

Une url urlrewritée doit-elle pointer ( avant url rewriting ) vers une url existante ?

Supposons que je fasse ceci :


location /to_data/pronos/lendemain

rewrite /to_data/pronos/lendemain/pronostics-courses.php /pwa.php?type=LENDPRO break;


Deux solutions :

- pronostics-courses.php existe, elle est redirigée vers pwa.php

Si pronostics-courses.php a une erreur de parsing, qu'est-ce qui se passe ?

- pronostics-courses.php n'existe pas : Y a-t-il erreur 404 ou redirection ?

Merci beaucoup de vos réponses.
 
WRInaute accro
J'ai un bug.

Après activation du SW, l'url suivante est lancée en fetch :

http://localhost/to_data/pronos/lendemain/new-courses.php

Cette url en vrai n'existe pas, mais son fetch entraîne dans le SW déjà activé, la production du template et du cache pour Mustache.

Le template et le cache sont bien produits.

Il semble que le fetch se fasse quand même sur l'url new-courses.php ( erreur 404 ), alors que ce fetch ne devrait pas avoir lieu.

Voici le code dans le script externe au SW :

JavaScript:
            var myHeaders    = new Headers([
                ['Content-Type', 'text/html'],
                ['Cache-Control', 'no-cache, no-store, must-revalidate']
            ]);

        var request = new Request('http://localhost/to_data/pronos/lendemain/new-courses.php', myHeaders);

        fetch(request)
            .then((response) => {
                var text = response.text();
            }).then((text) => {
                console.log(text); 
                document.getElementById("body").innerHTML = text;
                return text;
            }).catch(error => {
                console.error('Erreur page html : ', error);
                });

Comment se fait-il que ce fetch ait lieu alors que le code dans le SW est censé ne pas le lancer ?

Merci beaucoup.
 
WRInaute accro
Bonsoir

Voici l'algorithme théorique :


Code:
                                               ALGORITHME
                                               **********

   URL        =>  URL REWRITEE     =>  URL LANCEE PAR pwa.php?params   =>   URLS LANCEES PAR SW.js         =>     PAGE HTML
----------        ------------         -----------------------------        ----------------------                ---------

   *.html      pwa.php?params          *.php ?                    template = templates             render(template, data);

                                                                       data = pronos_data_json.php&params


                                      PRISE EN CHARGE URLS PAR SW.js
                                      ******************************

--------------------------------------------------------------------------------------------------------------------------------------
|    N        |          N        |                  Y                |                Y                  |             Y            |
--------------------------------------------------------------------------------------------------------------------------------------


                                                REPONSE
                                                *******

                               DANS SW.js :  =>     NE PAS TENIR COMPTE DES URLS *.html,
                               ************
                                             =>     NE PAS TENIR COMPTE DES URLS pwa.php

                                             =>     TENIR COMPTE DES URLS REWRITEES *.php

                                             =>     LECTURE TEMPLATES & DATA

                                             =>     LECTURE  RENDER(TEMPLATE, DATA).
 
WRInaute accro
Bonjour

D'après l'algorithme ci-dessus, le script php lancé en fetch par pwa.php, est interprété par le SW pour charger le template et les data, passés à la moulinette de render(template, data) ( dans SW ) et le résultat text = render() devrait être reçu par pwa.php, et alimenter avec innerHTML(text) la page html.

Le code semble correct dans le SW, il y a même une Promise enveloppant la fonction render().

Mais le script php lancé par pwa.php n'existe pas, donc il y a erreur 404.

Comment éviter cette erreur, et transmettre le résultat de render(template, data) à pwa.php ?

Si je crée une url réelle *.php, qui ne donne pas lieu à url-rewriting, seulement à prise en charge par le SW, le fetch donnera uniquement le résultat de cette url ?

Merci beaucoup de votre aide.
 
WRInaute accro
Bon.

Le bug est que le fetch est bien pris en compte et dispatché vers les template et data, mais il y a un bug dans le template ou les data.

J'ai une question à propos de Mustache :

Si dans le template apparaissent plusieurs variables identiques ( noms et valeurs ), qui sont dans le même bloc ( externe ) et non consécutives, est-ce qu'il suffit dans les data de ne les mentionner qu'une seule fois/variable ?

Ou bien, dans les data, toutes les valeurs doivent y figurer ?

Merci beaucoup de vos réponses.
 
WRInaute accro
Bonjour

Voilà la structure de mon template :

Code:
 nonce
 nonce
 nonce
 nonce
 canonical_url
 title
 description
 courses_du
 liste_des_courses
 canonical_url
 liste_des_courses
 canonical_url
 liste_des_courses
 liste_des_courses
 liste_des_courses
 canonical_url

 #menu_list
 menu_web_url_uri
 menu_page
 menu_page
 /menu_list

 title

 #liste_reunions
 reunion_num
 reunion_ancre
 reunion_name
 #liste_reunions_courses
 url_course
 nom_course
 nom_course
 num_course
 url_course
 nom_course
 nom_course
 url_course
 nom_course
 #liste_courses_paris
 class_pari
 nom_pari
 nom_pari
 /liste_courses_paris
 url_course
 nom_course
 heure
 com_1
 url_course
 nom_course
 nbpartants
 com_2
 /liste_reunions_courses
 /liste_reunions

 #footer_list
 footer_class
 footer_url
 footer_name
 /footer_list

 url_mentions_legales
 nom_mentions_legales
 nom_mentions_legales


Il contient plusieurs variables de nom et valeurs identiques, situées dans le même bloc.

Faut-il que dans le data je mette plusieurs fois ces variables ?

Merci beaucoup.
 
WRInaute accro
Bonjour

Faut-il spécifier ceci pour un template Mustache :

<script id="template" type="x-tmpl-mustache">

Sinon, qui de la balise html5 <template>

Merci.
 
WRInaute accro
Ah, bah...

Cà marche maintenant pour les listes de courses d'aujourd'hui et lendemain.

Les templates et data passent.

Pour le reste des urls je vais investiguer.

Ah, bougre...
 
WRInaute accro
Pardon.

J'ai un problème avec des reader = body.getReader() qui sont déjà locked.

Il faut délocker les readers avec reader.releaseLock(), mais comment faire celà quand les reader sont déjà locked ?

Merci beaucoup de votre aide.
 
WRInaute accro
Rebonjour.

J'ai mis au point le Javascript.

Pour ce qui s'agit des data, je les charge sans cache, avec : "Cache-Control : nocache, must-revalidate".

Les templates devraient être cachés, puisqu'ils ne changent quasiment jamais.

Ils ont une response de type octet-stream, bien pris en charge par ma fonction getStreamToString(stream).

Mais celà arrive que je modifie des templates, donc le cache donne la version obsolète.

Que faire, pour cacher efficacement les templates, tout en adaptant le cache si besoin ?

Merci beaucoup.
 
WRInaute accro
Rebond.

Est-ce qu'une logique "stale-while-revalidate" pourrait répondre à ce topic ?

Les templates sont chargés très souvent.

Le cache d'abord, et revalidate du cache en même temps ?

Pas d'autres solutions ?

Merci beaucoup de votre aide.
 
WRInaute accro
Voilà voilà.

J'ai les listes de courses du lendemain, aujourdhui et passées ( avec les paramètres de date ), ainsi que la liste des courses des dix derniers jours.

Pour les pronostics ( lendemain, avec les paramètres réunion et course ) , çà s'affiche correctement sur https://rickkas7.github.io/mustache/ mais pas sur mon navigateur Brave.

Ma couche réseau ( service worker ), me semble correcte, et même je suis très fier de ma fonction streamToString(stream ), qui produit une Promise avec le string texte à partir d'un stream de content-type : application/octet-stream.

Avec une fonction récursive classique de mon cru.

Mes trois fonctions ( streamToString(stream), getResp(response) et fetchData(url, cache = null) ) sont des Promises qui fonctionnent parfaitement en interrelation avec des then.

D'un autre côté, j'ai souvent des libellés fixes ( pas des variables mustache ), qui transforment les voyelles accentuées ( réelles ) en mode html ave éperluette.

Comment empêcher cette traduction ?

Il s'agit de chaînes de caractères "en-dur" de type utf-8.

Merci beaucoup de votre aide.
 
WRInaute accro
Rebonjour

Dans cette fonction, il y a le bug : ".then n'est pas une fonction ".

Voici le code :

(response || fetchPromise)
.then((resp) => {

Celà se produit relativement aléatoirement.

C'est un code classique pour du "stale while revalidate".

Comment fiabiliser le code ?

Merci beaucoup pour votre aide.


JavaScript:
/* jshint esversion: 8 */

function fetchData(url, cache = null) {

    var tmp_resp    = null;

    return new Promise((resolve, reject) => {

        cache.match(url).then(function(response) {
            var fetchPromise = fetch(url, {
                headers: { 
                    "Cache-Control" : "no-cache, no-store, must-revalidate"
                }
            }).then(function(networkResponse) {
                if(networkResponse && networkResponse.ok) {
                    cache.put(url, networkResponse.clone());
                    return networkResponse;
                }
            });
            (response || fetchPromise)
                .then((resp) => {

                    if(resp && resp.ok) {

                        tmp_resp    = resp.clone();

                        contentType    = tmp_resp.headers.get("content-type");

                        console.log('contentType = ' + contentType);

                        if(contentType.indexOf("application/json") !== -1) {
                            tmp_resp.json()
                                .then((json) => {
                                    resolve(json);
                                });
                        } else if(contentType.indexOf("text/plain") !== -1 ||
                            contentType.indexOf("text/html") !== -1) {
                            tmp_resp.text()
                                .then((text) => {
                                    resolve(text);
                                });
                        } else {
                            reject('contentType inattendu : ' + contentType);
                        }
                    } else {
                        reject('response absente ou non valide.');
                    }
                }).catch((error) => {

                    reject('Erreur response absente ou non valide : ' + error);
                });
        });
    });
}
 

➡️ Offre MyRankingMetrics ⬅️

pré-audit SEO gratuit avec RM Tech (+ avis d'expert)
coaching offert aux clients (avec Olivier Duffez ou Fabien Faceries)

Voir les détails ici

coaching SEO
Haut