web-dev-qa-db-fra.com

Données et promesses des composants asynchrones VueJS

Essayer VueJS 2.0 RC et utiliser l'API fetch pour charger des données pour certains composants. Voici un faux exemple:

const Component = {
  template: '#comp',
  name: "some-component",
  data: function () {
    return {
      basic: data.subset,
      records: function () {
        return fetch('/datasource/api', {
          method: 'get'
        }).then(function (response) {
          return response.json();
        }).then(function (response) {
          if (response.status == "success") {
            return response.payload;
          } else {
            console.error(response.message);
          }
        }).catch(function (err) {
          console.error(err);
        });
      }
    }
  }
};

L'objet data est un état d'application global, défini avant l'initialisation de l'application, et seul un sous-ensemble de celui-ci est nécessaire dans le composant, d'où cette partie. L'ensemble principal des données du composant provient d'un autre point de terminaison que j'essaie d'appeler. Cependant, la propriété data attend un objet et récupère une promesse qu'elle ne peut pas vraiment utiliser dans le contexte d'une boucle dans le modèle pour le rendu, etc. (par exemple v-for="record in records")

Suis-je en train de mal faire ça? Quelle est l'approche pour obtenir la mise à jour de la propriété data records une fois qu'elle est entièrement récupérée? Existe-t-il un moyen de forcer le code à s'arrêter jusqu'à ce que la promesse soit résolue (en le faisant effectivement synchroniser)? Le composant est inutile sans les données de toute façon, il y a donc une période d'attente avant de pouvoir être utilisé malgré tout.

Quelle est la bonne façon de remplir de manière asynchrone le champ de données d'un composant sans utiliser des plugins comme vue-async ou vue-resource?

(Je sais que je pourrais utiliser les méthodes XHR/jQuery d'appels ajax non promis, mais je veux apprendre à le faire en utilisant la récupération)


Mise à jour: j'ai essayé de définir un hook créé et une méthode pour charger les données, comme ceci mais pas de dés - dans mes propres expériences, la propriété records ne se met pas à jour une fois qu'elle est chargée. Il ne change pas, même si les données sont récupérées avec succès (se connecte avec succès à la console).

Pourrait avoir quelque chose à voir avec moi en utilisant vue-router et le composant que j'ai affaire à déclencher lorsqu'un lien est cliqué, par opposition à être un composant Vue ordinaire. En savoir plus ...


Mise à jour # 2: Si je continue à étudier l'approche jsfiddle ci-dessus et à me connecter this.records et response.payload à la console, il affiche l'objet d'enregistrements en cours de remplissage. Cependant, cela ne semble pas déclencher de changement dans le modèle ou le composant lui-même - en inspectant avec les outils Vue dev, la propriété records reste un tableau vide. En effet, si j'ajoute une méthode logstuff et un bouton dans le modèle qui l'appelle, puis avoir ce journal de méthode this.records dans la console, il enregistre un observateur avec un tableau vide:

enter image description here

Maintenant, je me demande pourquoi la propriété data d'un composant ne serait pas mise à jour même après avoir été explicitement définie sur une autre valeur. J'ai essayé de configurer un observateur pour $route qui déclenche la méthode reload, mais pas de dés - chaque chargement suivant de cette route réédite en effet la récupération, et les journaux de la console this.records tel qu'il est rempli (à partir de l'extraction), mais le "vrai" this.records reste un tableau vide.

11
Swader

La solution a été l'approche jsfiddle, avec une touche. Cette partie:

reload: function () {
      fetch('/data/api', {
        method: 'get'
      }).then(function (response) {
        return response.json();
      }).then(function (response) {
        if (response.status == "success") {
          this.records = response.payload;
        } else {
          console.error(response.message);
        }
      }).catch(function (err) {
        console.error(err);
      });
    }

avait besoin d'une .bind(this) dans la partie qui définit la valeur this.records après la récupération, comme ceci:

reload: function () {
      fetch('/data/api', {
        method: 'get'
      }).then(function (response) {
        return response.json();
      }).then(function (response) {
        if (response.status == "success") {
          this.records = response.payload;
        } else {
          console.error(response.message);
        }
      }.bind(this)).catch(function (err) {
        console.error(err);
      });
    }

Ce post était ce qui l'a fait cliquer pour moi.

Leçon apprise: dans JS moderne, gardez toujours la portée à l'esprit.

5
Swader