ES6 async/await in Klassen

Ich versuche, eine Klasse zu erstellen, die senden eine post-Anforderung (login), speichern Sie das cookie und verwenden das cookie für andere Vorgänge wie das herunterladen einer Datei.

Erstellte ich einen lokalen server, der zum empfangen einer http-post-Methode mit user und Passwort und einen router namens /download wird nur zugegriffen werden, wenn der Benutzer angemeldet ist, sonst wird es zurück you need to log in.

Problem:
Dies ist der Prototyp meiner Klasse (vor der hand):

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
  }
}

Wie Sie sehen können, im code oben, ich brauche das cookie für zwei Operationen, die download und query also wenn ich etwa die Schaffung einer init Methode, mit der die Initiale Operationen wie login, und rufen Sie es direkt in dem Konstruktor, so wird es initialisiert und legen Sie die cookie auf die variable this.cookie um überall benutzen, aber es funktioniert nicht, es scheint, dass init wird aufgerufen, nachdem jede andere Methode.

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()

Es zu mir zurück, die ich brauche, um sich anzumelden (server-Antwort)... ABER es funktioniert, wenn ich dies ändern:

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))
}

Funktioniert es nur, wenn ich den Anruf init im download Methode.

Wenn ich console.log(this.cookie) im download es gibt eine leere CookieJar und wenn ich das gleiche in init wird es wieder den richtigen cookie, aber es scheint NACH die Ausführung der herunterladen auch wenn ich aufgerufen auf der Konstruktor vor dem Aufruf download.

Wie zu lösen? Ich danke Ihnen sehr.

@edit

Ich die änderungen vorgenommen, die @agm1984 und @Jaromanda X mir gesagt, aber es funktioniert immer noch nicht 🙁

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))

Aber dann wieder... es funktioniert nicht, es sei denn, ich nenne init innen download.

  • Ich verstehe nicht, warum ich zurückkehren würde, nichts als die Operationen innerhalb init und download braucht nicht geteilt zu werden und überall die request-promise-native wird, setzen Sie das Glas in die this.cookie für mich (was ich brauche), aber die Sache ist die, um die Dinge laufen werden. Hinzufügen await init() im download ist, verhält sich wie "ich muss warten, bis init zu beenden und dann weiter" (so ähnlich), aber als ich rief this.init im Konstruktor ich dachte, es wäre nicht nötig.
  • Sorry, ja, habe ich deinen code falsch gelesen
  • wie gesagt, ich habe falsch gelesen, Ihren code, ignorieren meine änderungen :p - die meisten von Ihnen sind nicht erforderlich, da ich Mist gebaut meine - Kenntnisse von async/await :p
  • Das ist okay, Sie versucht zu helfen, und ich verstehe, was du meinst. Trotzdem vielen Dank.
  • das problem ist jetzt, dass download nicht warten init
  • im Konstruktor, versuchen Sie this.initp = this.init(); ... dann in download hinzufügen await this.initp; als erste Zeile
  • Genau, ich will nicht fordern init in jede einzelne Methode, die ich benötigen den cookie also in einer logischen Weise, die ich dachte,: was ich schuf eine Methode, die aufgerufen wird, sobald im Konstruktor und verwendet danach überall, auch in der Theorie, es funktioniert wie ein Charme, aber in der Praxis nah. Ich dachte, dass die await würde den trick tun und warten, bis es beendet, und ich rufe download über die konkrete Methode der ImageDownloader ich auch aber, dass es nennen würde download nach init sowieso.
  • Es funktioniert, aber es geht um die Anforderungen an login über und immer wieder, jedes mal, wenn ich rufe download oder Verwendung in einer anderen Methode, es ist das gleiche zu nennen: await this.init() zu await this.initp
  • nicht, wenn Sie das tun, was ich mir als letztes vorgeschlagen ... hinzufügen this.initp = this.init(); zu constructor (einmal ausgeführt), dann fügen Sie await this.initp; als erste Zeile download aber Sie müssen auch return await request({ im download (wie Sie JETZT tun), wenn Sie wollen, um die aufgelöste Daten
  • Ja, du hast Recht, es funktioniert, die einzige Sache ist, dass ich bin nicht so bequem, noch, und nicht glücklich darüber, dass es keine andere Möglichkeit, das zu tun, ohne die Notwendigkeit, die Berufung await this.initp in jeder Methode muss der cookie, es sieht so spaghetti. 🙁
  • Ich würde trennen Sie die Anliegen und Spritzen Sie das cookie in die Bild downloader so, dass Ihr code wird mehr wie: const cookie = await getCookie(username, password); const image = await (new ImageDownloader(cookie)).download();
  • Es gibt 2 Möglichkeiten. Entweder Sie müssen zur Aufrechterhaltung einer Sitzung (Anfrage-Sitzung) oder Sie beibehalten müssen cookies wie @k0pernikus vorgeschlagen.

InformationsquelleAutor vajehu | 2017-10-07
Schreibe einen Kommentar