web-dev-qa-db-fra.com

Requête correcte avec async / wait dans Node.JS

Dans mon programme, je lance un appel async pour ma fonction à partir d'un autre module d'API:

var info = await api.MyRequest(value);

Code du module:

var request = require("request")

module.exports.MyRequest = async function MyRequest(value) {
    var options = {
        uri: "http://some_url",
        method: "GET",
        qs: {  // Query string like ?key=value&...
            key : value
        },
        json: true
    }

    try {
        var result = await request(options);
        return result;
    } catch (err) {
        console.error(err);
    }
}

L'exécution retourne immédiatement, cependant result et donc info contient l'objet de requête et le corps de la requête - info.body comme key=value&..., corps de réponse non requis.

Qu'est-ce que je fais mal? Comment réparer? Quelle est l'utilisation appropriée de request avec async, ou cela ne fonctionne correctement qu'avec les promesses mentionnées ci-dessous: Pourquoi wait ne fonctionne pas pour le module de requête de nœud ? Après l'article mentionné, il est possible: Mastering Async Await in Node.js .

21
Aleksey Kontsevich

Vous devez utiliser le module request-promise, Pas le module request ou http.request().

await fonctionne sur les fonctions qui renvoient une promesse et non sur les fonctions qui renvoient l'objet request et vous demandent d'utiliser des rappels ou des écouteurs d'événement pour savoir quand les tâches sont terminées.

Le module request-promise Prend en charge les mêmes fonctionnalités que le module request, mais les fonctions asynchrones qu’il renferme promettent de vous permettre d’utiliser .then() ou await avec elles. plutôt que les rappels attendus par le module request.

Donc, installez le module request-promise et changez ensuite ceci:

var request = require("request");

pour ça:

const request = require("request-promise");

Ensuite, vous pouvez faire:

var result = await request(options);
41
jfriend00

Bien sûr, vous pouvez aussi faire ce qui suit. Si ce dont vous avez besoin ne renvoie pas Promise par défaut, vous pouvez le fournir via une nouvelle méthode Promise. La réponse ci-dessus est cependant moins commentée.

async function getBody(url) {
  const options = {
    url: url,
    method: 'GET',
  };

  // Return new promise
  return new Promise(function(resolve, reject) {
    // Do async job
    request.get(options, function(err, resp, body) {
      if (err) {
        reject(err);
      } else {
        resolve(body);
      }
    })
  })
}
12
user3520261

J'ai juste réussi à le faire fonctionner avec asynchrone/wait. Je l'ai enveloppé dans une fonction promisifiedRequest pour renvoyer un promise qui exécute la requête callback et le résout ou le rejette en fonction de error et response.

const request = require('request');

const promisifiedRequest = function(options) {
  return new Promise((resolve,reject) => {
    request(options, (error, response, body) => {
      if (response) {
        return resolve(response);
      }
      if (error) {
        return reject(error);
      }
    });
  });
};

(async function() {
  const options = {
    url: 'https://www.google.com',
    method: 'GET',
    gzip: true,
    headers: {
      'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.96 Safari/537.36'
    }
  };

  let response = await promisifiedRequest(options);

  console.log(response.headers);
  console.log(response.body);
})();
0
cbdev420