Grand remplacement

Je continue mes explorations pour voir si remplacer jQuery peut être fait sans (trop de) douleurs.

Mes derniers essais à ce sujet concernent les requêtes AJAX qu’on fait un peu partout pour récupérer des infos depuis le serveur sans recharger toute la page. Exemple avec un de mes plugins qui vérifie toutes les 5 minutes si le serveur répond.

Jusqu’alors j’avais ceci pour faire la requête (sachant que la réponse, si elle arrive, est au format XML) :

$.get('services.php', {
  f: 'dmHostingMonitorPing',
  xd_check: dotclear.nonce,
})
  .done((data) => {
    showStatus($('rsp[status=failed]', data).length > 0 ? false : true);
  })
  .fail((jqXHR, textStatus, errorThrown) => {
    window.console.log(`AJAX ${textStatus} (status: ${jqXHR.status} ${errorThrown})`);
    showStatus(false);
  });

Je me sers de jQuery pour effectuer la requête GET (ligne 1) et pour faire une recherche dans la réponse (ligne 6) quand elle parvient.

Traduit en javascript pur, ça donne ceci :

let service = new URL('services.php', window.location.origin + window.location.pathname);
service.search = new URLSearchParams({
  f: 'dmHostingMonitorPing',
  xd_check: dotclear.nonce,
}).toString();

fetch(service)
  .then((p) => {
    if (!p.ok) {
      throw Error(p.statusText);
    }
    return p.text();
  })
  .then((data) => {
    const parser = new DOMParser();
    const rsp = parser.parseFromString(data, 'text/xml');
    const status = rsp.querySelector('rsp[status=failed');
    showStatus(status === null);
  })
  .catch((error) => {
    console.log(error);
    showStatus(false);
  });

C’est plus verbeux, certes, mais on retire toute dépendance à jQuery.

Ça le serait probablement un peu moins si les réponses étaient retournées sous forme JSON, probablement, puisqu’on pourrait utiliser un return p.json(); en ligne 12 et ensuite traiter le paramètre data (ligne 14) comme un objet javascript avec :

  .then((data) => {
    showStatus(data?.rsp?.status !== 'failed');
  })

Cela dit il y a des cas où récupérer la réponse au format XML est pratique, en particulier pour les modules de tableau de bord qui affichent des listes d’éléments (billets, commentaires, …), reçu correctement formatés et affichable dans la foulée.

Je me demande s’il ne faudrait pas étendre un peu le serveur REST pour permettre de définir le format attendu de la réponse (XML par défaut, ou JSON) …

Et pour aller plus loin, je pense qu’on pourrait même coder une fonction un peu plus générique du style1 :

dotclear.services = (fn, onSuccess = (data) => {}, onError = (error) => {}, get = true, params = {}, format = 'XML') => {
  const service = new URL('services.php', window.location.origin + window.location.pathname);
  dotclear.mergeDeep(params, { f: fn, xd_check: dotclear.nonce });
  const init = { method: get ? 'GET' : 'POST' };
  if (get) {
    service.search = new URLSearchParams(params).toString();
  } else {
    if (format === 'XML') {
      const data = new FormData();
      Object.keys(params).forEach((key) => data.append(key, params[key]));
      init.body = data;
    } else {
      init.headers = new Headers({ 'Content-Type': 'application/json' });
      init.body = JSON.stringify(params);
    }
  }
  fetch(service, init)
    .then((p) => {
      if (!p.ok) {
        throw Error(p.statusText);
      }
      return format === 'XML' ? p.text() : p.json();
    })
    .then((data) => onSuccess(data))
    .catch((error) => onError(error));
};

Pour ensuite l’utiliser comme ceci :

dotclear.services(
  'dmHostingMonitorPing',
  (data) => {
    const parser = new DOMParser();
    const rsp = parser.parseFromString(data, 'text/xml');
    const status = rsp.querySelector('rsp[status=failed');
    showStatus(status === null);
  },
  (error) => {
    console.log(error);
    showStatus(false);
  },
);

Ou comme cela avec le format JSON :

dotclear.services(
  'dmHostingMonitorPing',
  (data) => {
    showStatus(data?.rsp?.status !== 'failed');
  },
  (error) => {
    console.log(error);
    showStatus(false);
  },
  true,
  {},
  'JSON'
);

Dans ce cas on est pas loin de la simplicité d’appel de l’équivalent jQuery (voir premier bloc de code au début de ce billet).

Nota : je n’ai pas testé le cas où le format choisi serait JSON.


  1. Attention, c’est juste un premier jet d’une fonction utilitaire, y’a surement moyen d’organiser ça un peu mieux, en particulier sur la gestion des paramètres optionnels ↩︎

Ajouter un commentaire

Les champs suivis d'un * sont obligatoires

Les commentaires peuvent être formatés en utilisant la syntaxe Markdown Extra.

Ajouter un rétrolien

URL de rétrolien : https://open-time.net/trackback/15280

Haut de page