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
unddownload
braucht nicht geteilt zu werden und überall dierequest-promise-native
wird, setzen Sie das Glas in diethis.cookie
für mich (was ich brauche), aber die Sache ist die, um die Dinge laufen werden. Hinzufügenawait init()
imdownload
ist, verhält sich wie "ich muss warten, bisinit
zu beenden und dann weiter" (so ähnlich), aber als ich riefthis.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 warteninit
- im Konstruktor, versuchen Sie
this.initp = this.init();
... dann indownload
hinzufügenawait 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 dieawait
würde den trick tun und warten, bis es beendet, und ich rufedownload
über die konkrete Methode derImageDownloader
ich auch aber, dass es nennen würdedownload
nachinit
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()
zuawait this.initp
- nicht, wenn Sie das tun, was ich mir als letztes vorgeschlagen ... hinzufügen
this.initp = this.init();
zuconstructor
(einmal ausgeführt), dann fügen Sieawait this.initp;
als erste Zeiledownload
aber Sie müssen auchreturn await request({
imdownload
(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.
Du musst angemeldet sein, um einen Kommentar abzugeben.
Hier das problem, dass
init
asynchron ist. Verwenden Sie es wie folgt:Den
download
Funktion wird ausgeführt, währendinit
noch nicht zu Ende noch.Ich würde nicht nennen die init-Methode in den Konstruktor. Was ich tun würde, ist so etwas wie dies:
1 - entfernen Sie den init-Aufruf vom Konstruktor.
2 - verwenden Sie die Klasse wie folgt aus:
und wenn Sie den Aufruf init in einem
async
Funktion können Sie tun: