J'ai du mal à enrouler ma tête autour d'une disposition de promesse imbriquée où un seul objet est retourné à la fin de celui-ci. Mon code actuel est le suivant:

Routeur

router.get(`/${config.version}/event/:id?`, function (req, res, next) {
    var event = new Event(req, res, next);
    event.getInfo(req.params.id).then((info) => {
        res.send(info);
    });
});

Une fonction

getInfo(id) {
    db.main('events').where('id', id).select()
    .then((result) => {
        if(result.length > 0) {
            var event = result[0];

            //regular functions
            event.status = this.getStatus(id);
            event.content = this.getContent(id);
            event.price = this.getPrice(id);

            //promise functions
            var users = this.getUsers(id);
            var hosts = this.getHosts(id);

            Promise.all([users, hosts]).then(values => {
                event.users = values[0];
                event.hosts = values[1];

                //return whole event object to router
                return event;
            })
            .catch((err) => {
                return {
                    result: 'error',
                    error: err
                };
            });

        } else {
            return {
                    result: 'error',
                    error: "Event does not exist"
                };
        }
    }).catch((e) => {
        return {
                    result: 'error',
                    error: "Could not retrieve event info"
                };
    });
}

Comme vous pouvez le voir, le routeur lance un appel pour obtenir des informations sur un événement. La fonction effectue ensuite un appel à la base de données et obtient des données d'événement. Par la suite, je dois obtenir les utilisateurs et les hôtes de l'événement à partir d'une table différente, ajouter également ces informations à l'objet événement, puis renvoyer l'objet entier au routeur pour être envoyé au client.

Lorsque je fais cela, j'obtiens une erreur car je ne renvoie pas de promesse à partir de la fonction getInfo, mais je ne sais pas comment ou quelle promesse je suis censé retourner.

J'apprécierais de l'aide avec ceci. Merci

1
Reza Karami 8 août 2016 à 23:59

3 réponses

Meilleure réponse

Utiliser .then signifie que vous retournez une promesse.

function getInfo(id) {
  return new Promise(function(resolve, reject) {
    resolve('yay!');
  })
}
getInfo().then(function(result) { //result = yay! });

Pour faire fonctionner votre code, remplacez simplement tous les retours par resolves, les erreurs par rejets et enveloppez le tout avec un return new Promise comme je l'ai fait.

getInfo(id) {
  return new Promise(function(resolve, reject) {
    db.main('events').where('id', id).select()
      .then((result) => {
        if (result.length > 0) {
          var event = result[0];

          //regular functions
          event.status = this.getStatus(id);
          event.content = this.getContent(id);
          event.price = this.getPrice(id);

          //promise functions
          var users = this.getUsers(id);
          var hosts = this.getHosts(id);

          Promise.all([users, hosts]).then(values => {
              event.users = values[0];
              event.hosts = values[1];

              //return whole event object to router
              resolve(event);
            })
            .catch((err) => {
              reject({
                result: 'error',
                error: err
              });
            });

        } else {
          reject({
            result: 'error',
            error: "Event does not exist"
          });
        }
      }).catch((e) => {
        reject({
          result: 'error',
          error: "Could not retrieve event info"
        });
      });
  });
}
1
Bamieh 8 août 2016 à 21:08

C'est une combinaison de plusieurs choses, mais la principale est que vous ne renvoyez jamais rien de getInfo, donc votre gestionnaire de routeur appelle .then le undefined.

N'appelez pas .catch (sans throw y entrer) le Promise s que vous avez l'intention de renvoyer pour qu'un appelant consomme. Cela ne permet pas d'utiliser .catch, car vous avez récupéré la chaîne Promise en une chaîne résolue.

Tout ce que vous retournez dans un .then sera fusionné dans la chaîne de promesses, donc ce n'est pas réellement une "promesse qui se résout par une promesse". Votre code entier pourrait être remplacé par:

getInfo (id) {
    return db.main('events').where('id', id).select()
    .then(result => {
        if (result.length == 0) {
            // you can also just throw your error object thing,
            // but standard Error are generally the convention
            throw new Error('Event does not exist')
        }

        const [event] = result

        event.status = this.getStatus(id)
        event.content = this.getContent(id)
        event.price = this.getPrice(id)

        return Promise.all([this.getUsers(id), this.getHosts(id)])
        .then(([users, hosts]) => {
            event.users = users
            event.hosts = hosts

            // this is the only value that
            // this.getInfo(id).then(value => {/* ... */}) will see
            return event
        }
    })
}
0
Jessidhia 9 août 2016 à 14:35

Enveloppez simplement votre code asynchrone dans Promise comme ceci:

getInfo(id) {
  return new Promise(function(resolve, reject) {
    db.main('events').where('id', id).select()
    .then((result) => {
       //...
       resolve(/* result */)
       // OR
       reject(/* Error */)
  })
}

Remarque: Utilisez resolve et reject à la place return

0
Nosyara 8 août 2016 à 21:06