2
votes

Envoi de plusieurs requêtes API à l'aide de Promise

Comment envoyer plusieurs requêtes API? donc j'ai ce code ci-dessous

async function removeProducts() {
    const productID = [12, 43, 65, 87, 45, 76, 87];
    const result = await Promise.all(productID.map(id => {
        API.removeItem(id, (err, response) => {
            if (response.status === 'success') {
                console.log('remove a product');
            }else {
                console.log(err); 
        }
        });
    }));
}

Le problème est qu'il n'attend pas que la première demande d'API se termine et récupère la réponse, et ne supprime qu'un seul élément. Donc, fondamentalement, je voulais que cela devienne synchrone et c'est pourquoi j'utilise async await pour résoudre mon problème.

 const productID= [12, 43, 65, 87, 45, 76, 87];
    productID.map(id => {
     API.removeItem(id, (err, response) => {
       if (response.status === 'success') {
           console.log('remove a product');
        }else {
          console.log(err); 
        }
     })
})

Le résultat est presque le même que le premier extrait de code, mais cette fois, il a pu supprimer 2 produits. Je veux que la demande suivante ne soit faite que si la demande précédente est terminée. Comment puis-je faire cela?


1 commentaires

4 Réponses :


1
votes

En fait, Promise.All () effectue la requête parallèle, ce n'est donc pas une solution que vous recherchez.

Ce dont vous avez besoin, c'est de produire le résultat, puis de faire une autre demande et ainsi de suite. Pour cela, vous avez besoin de API.removeItem pour renvoyer Promise . Si ce n'est pas le cas, vous pouvez encapsuler cette fonction à l'aide de l'API Promise pour renvoyer Promise.

 const productID = [12, 43, 65, 87, 45, 76, 87];
    async function removeProducts() {
       for (let i = 0; i < productID.length; i++) {
            const result = await removeItem(productID[i]); // will return resolved value here
            // sequence
          }
     }

Vous pouvez maintenant utiliser cette fonction pour obtenir le résultat.

    async function removeItem(id) {
      return new Promise((resolve, reject) => {
        API.removeItem(id, (err, response) => {
          if (response.status === 'success') {
            resolve("message or data"); // or pass id or anything
          } else {
            console.log(err);
            reject(err)
          }
        })
      })
    }

0 commentaires

2
votes

Le problème avec votre deuxième tentative est que Promise.all () prend un tableau de promesses comme argument. La fonction Promise.all () renvoie également une promesse elle-même qui est résolue lorsque chaque promesse du tableau transmis est résolue.

Le array.map ne retourne pas une promesse, il renvoie un nouveau tableau avec les résultats de chaque élément du tableau appelé avec la fonction fournie. En savoir plus sur la fonction de carte ici a >.

Créez plutôt une fonction wrapper pour l'appel d'API qui renvoie une promesse.

const productID = [12, 43, 65, 87, 45, 76, 87];

let removeProductID = (id) => {
    return new Promise((resolve, reject) => {
        API.removeItem(id, (err, response) => {
            if (response.status === 'success') {
                console.log('remove a product');
                resolve(response);
            } else {
                console.log(err);
                reject(err);
            }
        })
    });
}

let removeAllProductIDs = async () => {
    for(let id of productID) {
        await removeProductID(id);
    }
}

removeAllProductIDs();


0 commentaires

0
votes
const productID = [12, 43, 65, 87, 45, 76, 87];
function process() {
    if (productID.length == 0) return;

    var id = productID.pop();
    API.removeItem(id, (err, response) => {
       if (response.status === 'success') {
           console.log('remove a product');
           process(); // process next item if success
        } else {
          console.log(err); 
        }
    });
};

process();

0 commentaires

0
votes

Comme les autres réponses, commencez par promettre API.removeItem (Si votre environnement est Node.js, vous pouvez utiliser util.promisify , sinon utilisez le constructeur Promise comme indiqué dans d'autres réponses):

const removeItems = ids => ids.reduce((acc, id) => (
  acc.then(() => removeItem(id))
), Promise.resolve());

removeItems([12, 43, 65, 87, 45, 76, 87]);

Ensuite, si cela ne vous dérange pas d'intégrer un module tiers, vous pouvez utiliser async-af (un module que je gère) pour parcourir les ID séquentiellement en utilisant un async forEach :

const AsyncAF = require('async-af');

const removeItems = ids => AsyncAF(ids).series.forEach(removeItem);

removeItems([12, 43, 65, 87, 45, 76, 87]);

Vous pouvez également utiliser vanilla JS pour parcourir les identifiants séquentiellement; par exemple, voici une implémentation utilisant Array.prototype.reduce:

const {promisify} = require('util');

const removeItem = promisify(API.removeItem);


0 commentaires