1
votes

URL de basculement Javascript fetch ()

J'ai un tableau d'URL que j'aimerais exécuter une requête fetch () à:

const urls = [
  'https://dewnuf111111.com/configuration',
  'https://dewnuf222222.com/configuration',
  'https://bcsmania.co.uk/test.json'
];

let obj = {a: 'test'};
let counter = 0;

function ajax(url) {
  // Check for for last URL in the array
  if (counter < urls.length) {
    return fetch(url)
      .then(response => {
        // Combine objects
        obj = Object.assign(obj, response.json());
        console.log(urls[counter], obj);
        return Promise.resolve(obj);
      }).catch(error => {
        counter++;
        // Fetch next URL
        ajax(urls[counter]);
      });
  }
}

function getConfigurations() {
  return ajax(urls[counter]);
}

getConfigurations().then((configurations) => {
  console.log('DONE', configurations);
});

Si la récupération détecte une erreur (par exemple, le le site n'existe pas, erreur interne, etc.), j'aimerais qu'il tente la prochaine URL, j'ai donc ajouté un incrémenteur. Une fois qu'il a atteint une URL de travail et fait une demande avec succès, il devrait alors simplement console.log ('DONE') , mais je n'arrive pas à le faire fonctionner.

Voici le code que j'ai écrit jusqu'à présent:

const urls = [
  'https://dewnuf111111.com/configuration',
  'https://dewnuf222222.com/configuration',
  'https://bcsmania.co.uk/test.json'
];

Voici un JSFiddle pour voir un aperçu.

Quelqu'un peut-il me dire où je pourrais me tromper? Dois-je rendre la fonction asynchrone puis attendre le résultat?


5 commentaires

Copie possible de manière propre d'attendre le premier vrai renvoyé par Promesse


Je pense que ce candidat en double est peut-être ce que vous voulez. Je ne sais pas si vous voulez que ceux-ci soient essayés séquentiellement et un à la fois (au lieu de tous en même temps).


return ajax (urls [compteur]);


@Kaiido - Ughr merci beaucoup. Je ne peux pas croire que je n'ai pas vu ça. Si vous souhaitez ajouter votre solution en tant que réponse ci-dessous, je l'accepterai avec plaisir.


Je cherchais une dupe (il doit y en avoir déjà une) mais je ne peux pas la trouver pour le moment, alors j'ai posté une CW.


3 Réponses :


2
votes

Vous devez renvoyer la promesse dans votre capture afin de pouvoir également la chaîner:

.catch(error => {
    counter++;
    // return Fetch next URL
    return ajax(urls[counter]);
  });


0 commentaires

1
votes

Ici, vous mélangez du code asynchrone avec du code de synchronisation. Puisque votre boucle est de nature synchronisée, elle n'attend pas le résultat et une fois le code résolu, elle imprime TERMINÉ. La solution la plus simple, vous pouvez utiliser async-await dans l'URL de la boucle. J'ai donné un exemple ci-dessous. Veuillez vérifier.

https://jsfiddle.net/gof91e6v/

const urls = [
  "https://dewnuf111111.com/configuration",
  "https://dewnuf222222.com/configuration",
  "https://bcsmania.co.uk/test.json"
];

let obj = { a: "test" };

async function getConfigurations(urls) {
  let result = null;
  if (counter < urls.length) {
    for (let count = 0, len = urls.length; count < len; count++) {
      try {
        result = await fetch(urls[count]);
      } catch (e) {}
      if (result) break;
    }
  }
  return result;
}

getConfigurations(urls).then(configurations => {
  console.log("DONE", configurations);
});


0 commentaires

1
votes

Je chercherais à séparer la récupération d'une liste d'URL de la façon dont vous la gérez (par exemple votre appel à Object.assign .)

Dans cette version, fetchFirstWorking code > accepte une liste d'urls et répond avec une promesse qui sera résolue avec le résultat de la récupération de la première URL en direct. Notez qu'il utilise la récursivité plutôt qu'un compteur, donc la gestion des états est réduite au minimum.

getConfiguration contient la logique métier.

const fetchFirstWorking = ( [url, ...urls], conf ) => url
  ? fetch (url, conf)
      .catch ( _ => fetchFirstWorking(urls) )
  : Promise .reject ('no urls could be loaded')

const getConfigurations = (urls) => 
  fetchFirstWorking(urls)
    .then ( res => res .json () )
    .then ( res => Object .assign ({a: 'test'}, res) )

const urls = [
  'https://dewnuf111111.com/configuration',
  'https://dewnuf222222.com/configuration',
  'https://dewnuf333333.com/configuration',
]

getConfigurations (urls)
  .then(console.log)
  .catch(console.warn)

Si vous remplacez la dernière URL par un autre factice, vous la verrez générer l'avertissement de la console à la place:

const fetchFirstWorking = ( [url, ...urls], conf ) => url
  ? fetch (url, conf)
      .catch ( _ => fetchFirstWorking (urls) )
  : Promise .reject ('no urls could be loaded')

const getConfigurations = (urls) => 
  fetchFirstWorking(urls)
    .then ( res => res .json () )
    .then ( res => Object .assign ({a: 'test'}, res) )

const urls = [
  'https://dewnuf111111.com/configuration',
  'https://dewnuf222222.com/configuration',
  'https://bcsmania.co.uk/test.json'
]

getConfigurations (urls)
  .then(console.log)
  .catch(console.warn)


0 commentaires