ES6 async/await dans les classes

Je suis en train de créer une classe qui va envoyer une requête post (login), enregistrer le cookie et l'utilisation de ce cookie pour d'autres opérations telles que le téléchargement d'un fichier.

J'ai créé un serveur local qui recevra une méthode http post avec d'utilisateur et le mot de passe et un routeur appelé /download qui ne seront accessibles que si l'utilisateur est connecté, sinon il sera de retour you need to log in.

Le problème:
C'est le prototype de ma classe (avant de la main):

const request = require('request-promise-native')

class ImageDownloader {
  constructor(username = null, password = null) {
    this.username = username
    this.password = password
    this.cookie = request.jar()

    this.init()
  }

  init() {
    //login and get the cookie
  }

  download() {
    //needs the cookie
  }

  query() {
    //needs the cookie
  }
}

Comme vous pouvez le voir dans le code ci-dessus j'ai besoin de le cookie pour deux opérations qui est download et query j'ai donc bien sur la création d'un init méthode qui vous permettra d'effectuer les opérations initiales telles que la connexion et l'appeler à droite dans le constructeur de sorte qu'il sera initialisé et mis le cookie sur la variable this.cookie à utiliser partout, mais ça ne fonctionne pas, il semble que init est appelé après que toutes les autres méthodes.

const request = require('request-promise-native')

class ImageDownloader {
  constructor(username = null, password = null) {
    this.username = username
    this.password = password
    this.cookie = request.jar()

    this.init()
  }

  async init() {
    await request({
      uri: 'http://localhost/login',
      jar: this.cookie,
      method: 'post',
      formData: {
        'username': 'admin',
        'password': 'admin'
      }
    }).catch(e => console.error(e))
  }

  async download() {
    await request({
      uri: 'http://localhost/download/image.jpg',
      jar: this.cookie
    })
    .then(b => console.log(b))
    .catch(e => console.error(e))
  }

  query() {
    //...
  }
}

const downloader = new ImageDownloader
downloader.download()

C'est en revenant à moi que j'ai besoin de vous connecter (réponse du serveur)... MAIS ça marche si je fais ce changement:

async download() {
  await init() //<<<<<<<<<<<<
  await request({
    uri: 'http://localhost/download/image.jpg',
    jar: this.cookie
  })
  .then(b => console.log(b))
  .catch(e => console.error(e))
}

Il ne fonctionne que si je l'appelle init dans le download méthode.

Si j'ai mis console.log(this.cookie) dans download elle renvoie un vide CookieJar et si je mets le même dans init il sera de retour le droit cookie, mais il semble APRÈS l'exécution de télécharger même quand je l'ai appelé sur le constructeur avant d'appeler download.

Comment résoudre ce problème? Je vous remercie beaucoup.

@edit

J'ai fait les modifications que @agm1984 et @Jaromanda X m'as dit mais ça ne fonctionne toujours pas 🙁

const request = require('request-promise-native')

class ImageDownloader {
  constructor(username = null, password = null) {
    this.username = username
    this.password = password
    this.cookie = request.jar()

    this.init().catch(e => console.error(e))
  }

  async init() {
    return await request({
      uri: 'http://localhost/login',
      jar: this.cookie,
      method: 'post',
      formData: {
        'username': 'admin',
        'password': 'admin'
      }
    })
  }

  async download() {
    return await request({
      uri: 'http://localhost/download/image.jpg',
      jar: this.cookie
    })
  }

  query() {
    //...
  }
}

const downloader = new ImageDownloader
downloader.download()
          .then(b => console.log(b))
          .catch(e => console.error(e))

Mais là encore... il ne fonctionne pas à moins que j'appelle init à l'intérieur de download.

  • Je ne comprends pas pourquoi je voudrais retourner tout ce que les opérations à l'intérieur init et download n'a pas besoin d'être partagé n'importe où et le request-promise-native va mettre le pot dans la this.cookie pour moi (ce dont j'ai besoin), mais le truc, c'est l'ordre des choses sont en cours d'exécution. L'ajout de await init() dans download est de se comporter comme "je dois attendre pour init à la fin et puis continuer" (quelque chose comme ça), mais comme je l'ai appelé this.init dans le constructeur, je pensais qu'il ne serait pas nécessaire.
  • Désolé, ouais, j'ai mal lu ton code
  • comme je l'ai dit, j'ai mal lu ton code, ignorer les modifications que j'ai apportées :p - la plupart d'entre eux ne sont pas requis que j'ai foiré mon la connaissance de async/await :p
  • C'est bien, vous avez essayé de l'aider et je comprends parfaitement ce que tu veux dire. Merci à vous de toute façon.
  • le problème est maintenant que download l'habitude d'attendre init
  • dans le constructeur, essayez d'ajouter this.initp = this.init(); ... puis dans download ajouter await this.initp; la première ligne
  • Exactement, je ne veux pas être l'appel de init dans chaque méthode unique j'ai besoin de le cookie, donc de façon logique, j'ai pensé: ce sujet j'ai créé une méthode qui est appelée une fois dans le constructeur et utilisé par la suite partout, eh bien, en théorie, il fonctionne comme un charme, mais dans la pratique, nah. Je pensais que le await ferait l'affaire et attendre jusqu'à ce qu'elle se termine, et comme je suis d'appeler download à l'aide de la méthode concrète de ImageDownloader j'ai aussi bien que qui il ferait appel download après init de toute façon.
  • Il ne fonctionne pas mais ça va faire des demandes de connexion, encore et encore chaque fois que j'appelle download ou l'utilisation d'une autre méthode, c'est la même chose pour appeler: await this.init() à await this.initp
  • pas si vous faites ce que je suggère ... ajouter this.initp = this.init(); à constructor (s'exécute une fois), puis ajouter await this.initp; comme la première ligne de download mais vous aurez également besoin de return await request({ dans download (comme vous le faites MAINTENANT) si vous souhaitez vous rendre à l'résolu de données
  • Oui, vous avez raison, il fonctionne, le seul truc c'est que je ne suis pas à l'aise encore et n'est heureux qu'il n'y a pas d'autre moyen de le faire sans avoir besoin d'appeler await this.initp dans chaque méthode qui doit le cookie, il ressemble tellement à spaghetti. 🙁
  • Je voudrais séparer les préoccupations et injecter le cookie dans l'image downloader pour que votre code devient de plus en plus comme: const cookie = await getCookie(username, password); const image = await (new ImageDownloader(cookie)).download();
  • Il y a 2 façons. Soit vous en avez besoin pour maintenir une session (demande de session) ou vous avez besoin de conserver les cookies que @k0pernikus suggéré.

InformationsquelleAutor vajehu | 2017-10-07