244 votes

Pourquoi ma fonction asynchrone renvoie-t-elle Promise { <pending> } au lieu d'une valeur ?

Mon code :

let AuthUser = data => {
  return google.login(data.username, data.password).then(token => { return token } )
}

Et quand j'essaie d'exécuter quelque chose comme ça :

let userToken = AuthUser(data)
console.log(userToken)

J'y vais :

Promise { <pending> }

Mais pourquoi ?

Mon objectif principal est d'obtenir un jeton de google.login(data.username, data.password) qui renvoie une promesse, dans une variable. Et seulement ensuite, effectuer certaines actions.

2 votes

@LoïcFaure-Lacroix , voir cet article : medium.com/@bluepnume/

0 votes

@LoïcFaure-Lacroix regarder à getFirstUser fonction

0 votes

Alors, qu'en est-il ? C'est une fonction qui renvoie une promesse.

350voto

Bamieh Points 4686

La promesse sera toujours vous connecter en attendant, tant que ses résultats ne sont pas encore résolue. Indépendamment de la promesse de l'état (résolus ou encore dans l'attente de), vous devez appeler .then sur la promesse de capturer les résultats:

let AuthUser = function(data) {
  return google.login(data.username, data.password).then(token => { return token } )
}

let userToken = AuthUser(data)
console.log(userToken) // Promise { <pending> }

userToken.then(function(result) {
   console.log(result) //will log results.
})

pourquoi est-ce?

Les promesses sont vers l'avant seulement, vous ne pouvez les résoudre une fois, et vous ne pouvez obtenir à leur valeur de transmettre à leurs .then ou .catch méthodes

Détails

Selon les Promesses/A+ caractéristiques:

La promesse de la procédure de résolution est un résumé de l'opération en prenant comme entrée d'une promesse et d'une valeur, que nous noterons [[Résoudre]](promesse, x). Si x est un thenable, il tente de rendre la promesse d'adopter l'état de x, sous l'hypothèse que x se comporte un peu comme un promesse. Sinon, il remplit la promesse avec la valeur x.

Ce traitement de thenables permet promesse des implémentations interagir, tant qu'ils exposent une des Promesses/A+-compatible alors la méthode. Il permet aussi de Promesses/A+ implémentations "assimiler" nonconformant implémentations raisonnablement puis des méthodes.

Cette spécification est un peu difficile à analyser, donc permet de le décomposer:

La règle est que, si la fonction dans l' .then gestionnaire retourne une valeur, l' Promise résout à cette valeur. Si la fonction renvoie un Promise, l'autre, alors la clause sera l' .then de l'état résolu de le retourné Promise. La façon dont il fonctionne réellement est décrite en détail ci-dessous:

1. Le retour de l' .then fonction sera la détermination de la valeur de la promesse.

function initPromise() {
  return new Promise(function(res,rej) {
    res("initResolve");
  })
}

initPromise().then(function(result) {
    console.log(result); // "initResolve"
    return "normalReturn";
})
.then(function(result) {
    console.log(result); // "normalReturn"
});

2. Si l' .then fonction renvoie une promesse, puis la volonté de ses promesse sera la volonté de ses prochaines .then de coeur.

function initPromise() {
  return new Promise(function(res,rej) {
    res("initResolve");
  })
}
initPromise().then(function(result) {
    console.log(result); // "initResolve"
    return new Promise(function(resolve, reject) {
       setTimeout(function() {
          resolve("secondPromise");
       }, 1000)
   })
})
.then(function(result) {
    console.log(result); // "secondPromise"
});

0 votes

Votre première ne fonctionne pas. Uncaught SyntaxError: Unexpected token . . Le second a besoin d'un retour pour Promise

0 votes

@zamil vous devez invoquer la fonction, comme dans le deuxième exemple. vous ne pouvez pas .then sur une fonction non invoquée. J'ai mis à jour la réponse

4 votes

Je mets ce site en signet pour pouvoir le garder. pour toujours. J'ai travaillé très longtemps pour trouver des règles vraiment claires et lisibles sur la façon de construire des promesses. Votre citation de Promesses/A+ spec est un exemple parfait de la raison pour laquelle il a été un PITA pour enseigner les promesses. C'est aussi la SEULE fois que j'ai vu setTimeout utilisé sans que cela n'embrouille la leçon elle-même. Et excellente référence, merci.

58voto

Marius Seack Points 18

Je sais que cette question a été posée il y a 2 ans, mais je rencontre le même problème et la réponse au problème est depuis ES2017, que vous pouvez simplement await la valeur de retour de la fonction (pour l'instant, cela ne fonctionne qu'en async fonctions), comme :

let AuthUser = function(data) {
  return google.login(data.username, data.password)
}

let userToken = await AuthUser(data)
console.log(userToken) // your data

3 votes

Vous n'avez pas besoin de la .then(token => return token) c'est juste un passage inutile. Renvoyez simplement l'appel de connexion à Google.

0 votes

Cette réponse est sans rapport avec la question. Le problème de l'affiche originale n'a rien à voir avec async/await de ES6. Les promesses existaient avant l'introduction de ce nouveau sucre syntaxique dans ECMAScript 2017 et elles étaient utilisées "sous le capot". Voir MDN sur async/await .

3 votes

Pour ES8 / Nodejs, des erreurs sont lancées si vous utilisez await en dehors d'une fonction asynchrone. Peut-être que le meilleur exemple ici serait de faire de la fonction AuthUser fonction async qui se termine ensuite par return await google.login(...);

5voto

Traktor53 Points 1375

Le site then renvoie une promesse en attente qui peut être résolue de manière asynchrone par la valeur de retour d'un gestionnaire de résultats enregistré dans l'appel à la méthode then ou rejeté en lançant une erreur dans le gestionnaire appelé.

Donc, appeler AuthUser ne va pas soudainement connecter l'utilisateur de manière synchrone, mais renvoie une promesse dont les gestionnaires alors enregistrés seront appelés après la réussite ( ou l'échec) de la connexion. Je suggérerais de déclencher tout le traitement de la connexion par une promesse then de la promesse de connexion. Par exemple, en utilisant des fonctions nommées pour mettre en évidence la séquence du flux :

let AuthUser = data => {   // just the login promise
  return google.login(data.username, data.password);
};

AuthUser(data).then( processLogin).catch(loginFail);

function processLogin( token) {
      // do logged in stuff:
      // enable, initiate, or do things after login
}
function loginFail( err) {
      console.log("login failed: " + err);
}

4voto

Hasan Tezcan Points 436

Si cette situation se produit pour une valeur multiple comme un tableau.

[ 
  Promise { <pending> },
  Promise { <pending> },
  Promise { <pending> },
  Promise { <pending> },
  Promise { <pending> }
]

Vous pouvez utiliser Promise.all() cela résoudra toutes les promesses.

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/all

2voto

Jesse Amano Points 508

Voir la section MDN sur Des promesses. En particulier, regardez le type de retour de then().

Pour se connecter, l'agent utilisateur doit soumettre une demande au serveur et attendre de recevoir une réponse. Étant donné que l'arrêt total de l'exécution de votre application pendant l'aller-retour d'une requête constitue généralement une mauvaise expérience pour l'utilisateur, pratiquement toutes les fonctions JS qui vous connectent (ou qui effectuent toute autre forme d'interaction avec le serveur) utilisent une Promise, ou quelque chose de très similaire, pour fournir des résultats de manière asynchrone.

Maintenant, remarquez aussi que return sont toujours évaluées dans le contexte de la fonction dans laquelle elles apparaissent. Ainsi, lorsque vous avez écrit :

let AuthUser = data => {
  return google
    .login(data.username, data.password)
    .then( token => {
      return token;
    });
};

la déclaration return token; signifie que la fonction anonyme qui est passée dans then() devrait retourner le jeton, et non pas que le AuthUser fonction devrait. Ce que AuthUser retourne le résultat de l'appel google.login(username, password).then(callback); qui se trouve être une promesse.

En fin de compte, votre rappel token => { return token; } ne fait rien ; au contraire, votre entrée dans then() doit être une fonction qui gère le jeton d'une manière ou d'une autre.

0 votes

@Src J'ai écrit ma réponse avant que l'auteur de la question ne précise qu'il cherchait un moyen de de manière synchrone retourner une valeur, et sans faire de suppositions sur leur environnement de développement ou leur version de langage au-delà de ce qui peut être déduit de l'extrait de code - c'est-à-dire qu'il est possible de supposer qu'il s'agit de ES6, mais pas nécessairement de ES7.

0 votes

@AhmadBamieh Très bien, je le ferai. Je suppose que le problème est que j'ai mal compris comment return est traitée avec la syntaxe de fermeture new(ish), dans ce cas -- eh bien, je désapprouve fortement cela, mais l'erreur est toujours la mienne et je m'en excuse.

0 votes

Je peux comprendre ce que vous ressentez car le retour devrait être synchrone, et il devrait rendre le contrôle à son appelant, qui est une fonction anonyme. Mais l'explication pour vous est que vous devriez noter que le type de retour de then() est un nouvel objet Promise, donc la valeur retournée par le callback est utilisée pour remplir ou rejeter la promesse. Mais, si le callback renvoie une autre promesse, alors la nouvelle promesse (celle renvoyée par then()) ne sera remplie que lorsque cette promesse sera remplie.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X