J'ai une fonction qui appelle une promesse. En cas de succès ou d'échec, je voudrais retourner certaines données au-delà de ce que la promesse renvoie.

J'ai pensé que cela pourrait fonctionner:

function foo() {
  const extra = 'bar'
  return thepromise().then((res) => {
    return {
      result: res,
      data: extra
    }
  }, (err) => {
    // this will not happen if an error is thrown in the called promise
    return {
      result: res,
      data: extra
    }
  })
}

foo().then((res) => { }, (err) => { // error result ends up here })

Cependant, cela ne fonctionne pas. si une erreur est lancée dans le thepromise, elle n'appellera pas le bloc catch mais le bloc catch de foo().

Quelle est la bonne façon de gérer cela? Je réussis avec un bloc try / catch mais je ne suis pas sûr que ce soit la meilleure approche:

function foo() {
  const extra = 'bar'
  return new Promise((resolve, reject) => {
    try {
      return thepromise(p)
    } catch (e) {
      reject(e)
    }
  })
  .then(function(res) {
    return {
      result: res,
      data: extra,
      status: 'success'
    }
  }, function(err) {
    return {
      result: err,
      data: extra
      status: 'error'
    }
  })
}
0
cyberwombat 7 août 2016 à 05:11

3 réponses

Meilleure réponse

Si vous souhaitez recevoir des extensions de Promises, bluebird dispose d'une méthode d'essai qui fait exactement ce dont vous avez besoin:

import Promise from 'bluebird';

// ...

return Promise
  .try(thepromise)
  .then(res => ({
    result: res,
    data: extra
  })
  .catch(err => ({
    result: res,
    data: extra
  });
0
Jacob 7 août 2016 à 02:50

Toute fonction conçue pour renvoyer une promesse ne doit pas déclencher d'exception ou d'erreur.

Si c'est le cas, il devrait être considéré comme un buggy.

Pour corriger une méthode de bug, au lieu de lever une exception, rejetez la promesse retournée.


Parfois, vous n'êtes pas en mesure de corriger le bogue sous-jacent, comme lorsque vous utilisez l'API de quelqu'un d'autre. Si tel est le cas, la première chose et la plus importante à faire est de signaler le bogue aux auteurs d'origine afin que le problème sous-jacent puisse être résolu.

Après avoir signalé le problème, vous pouvez envelopper la méthode buggy dans un utilitaire simple pour résoudre le problème:

function fixBrokenPromise(promise/*, args...*/) {
  var args = Array.prototype.slice.call(arguments, 1),
      ret;
  try {
    ret = promise.apply(null, args);
  } catch (ex) {
    ret = Promise.reject(ex);
  }
  return ret;
}

Cela peut être appelé comme:

fixBrokenPromise(thepromise/*, args you want to pass to thepromise */)
  .then(...resolve...,
        ...reject...);
1
zzzzBov 7 août 2016 à 02:29

L'erreur est considérée comme gérée à .catch(), ce qui retournerait une promesse résolue à .then() enchaîné. Vous pouvez throw l'erreur au prochain .catch()

function foo() {
  const extra = 'bar'
  return thepromise().then((res) => {
    return {
      result: res,
      data: extra
    }
  }, (err) => {
    throw new Error(JSON.stringify({
      result: err || "no rejection reason provided",
      data: extra
    }))
  })
}

var thepromise = () => Promise.reject();

foo().then(data => console.log("fulfilled", data))
.catch(err => console.log("catch", JSON.parse(err.message)))
0
guest271314 7 août 2016 à 02:45