2017-12-25 4 views
0

Ich habe Probleme damit, wie man das in nodejs richtig macht. Dieser versucht, zwei Dinge parallel zu tun:Richtiger Weg mit async/warten auf parallele Anrufe

  • lädt eine Webseite axios
  • erstellt ein Verzeichnis

Verwendung Wenn diese fertig sind:

  • speichern asynchron zu einer Datei führen de erstellt Verzeichnis

Dann wartet bis l getan

const uuidv1 = require('uuid/v1') 
 
const fs = require('fs') 
 
const util = require('util') 
 
const axios = require('axios') 
 
const path = require('path') 
 

 
const mkdir = util.promisify(fs.mkdir) 
 
const writeFile = util.promisify(fs.writeFile) 
 

 
const downloadPage = async (url='http://nodeprogram.com') => { 
 
\t console.log('downloading ', url) 
 

 
\t const fetchPage = async function() { 
 
\t \t const folderName = uuidv1() 
 
\t \t return axios 
 
\t \t \t .all([ 
 
\t \t \t \t mkdir(folderName), 
 
\t \t \t \t axios.get(url) 
 
\t \t \t ]) 
 
\t \t \t .then(axios.spread(function (f, r) { 
 
\t \t \t \t writeFile(path.join(__dirname, folderName, 'file.html'), r.data); 
 
\t \t \t })); 
 
\t } 
 

 
\t await fetchPage() 
 
} 
 

 
downloadPage(process.argv[2])

+0

Also, was ist die genaue Frage? –

+0

Wie man es richtig macht :-) Ich denke, es könnte einen Fehler bei der Platzierung von ascs/wartet und Rückkehr und Deklaration geben. – Jacco

+0

Nicht in der Nähe von Computer, um genaues Beispiel einzugeben, aber was ich jetzt sehe: 1. Entfernen Sie async in fetchPage-Deklaration. 2. Setzen Sie den Aufruf der Schreibdatei nach der fetchPage-Zeile ab, entfernen Sie also 'then ...' mit ihr in der fetchPage-Definition –

Antwort

0

Ihre Frage und Probe suchen widersprüchlich. Die Frage besagt, dass Sie Async verwenden und auf parallele Aufrufe warten müssen, aber Ihr Beispielcode zeigt, dass Sie sequenzielle Aufrufe anstelle von parallel benötigen.

Die beste Verwendung von Async/Awaits sind für sequenzielle Anrufe.

async Funktion ist eine Art Kurzschriftfunktion für 'Promise', bei der Dinge implizit ausgeführt werden, wie die Rückgabe als 'Entschlossenheit' betrachtet wird.

erwarten immer innerhalb async Funktion sein sollte, fügen erwarten auf Funktionen, die Sie für die weitere, bevor Sie fortfahren warten.

Syntax Änderung in erwarten Funktion ist, statt

somePromiseFunctionCall().then((someVarible) => {...}).catch(e => {}) 

Sie benötigen

const asyncFunction = async (parameters) => { 
    try { 
     // First Function call that returns Promise/async 
     someVariable = await somePromiseFunctionCall(); 
     // Second (sequential) call that returns Promise/async 
     someNewVariable = await someotherPromiseFunctionCall(); 
    } catch(e) { 
     throw new Error(e); 
    } 
} 

Jetzt in Ihrer Probe zu verwenden, wenn Ihre Forderung nach axios zurückkehren zu warten ist und Erstellen Sie dann einen Ordner und schreiben Sie das Ergebnis in eine Datei, die mit async ausgeführt werden kann und wartet.

0

ändern diese:

writeFile(path.join(__dirname, folderName, 'file.html'), r.data); 

dazu:

return writeFile(path.join(__dirname, folderName, 'file.html'), r.data); 

Sie müssen das Versprechen von writefile zurück, so dass es zu der Kette hinzugefügt wird, so dass das Versprechen Sie von fetchPage() Rückkehr bist ist verbunden mit der writeFile() Operation. Als Ihr Code ursprünglich war, wird der writeFile() Betrieb auf seine eigene Vorgehen der und ist überhaupt nicht mit dem Versprechen verbunden Sie von fetchPage() so Rückkehr wurden, wenn Sie tun:

await fetchPage() 

es nicht die writeFile() Betrieb erwartet wurde.


A gereinigt Version könnte wie folgt aussehen:

const downloadPage = (url='http://nodeprogram.com') => { 
    console.log('downloading ', url) 

    // don't really need this separate fetchPage() function  
    const fetchPage = function() { 
     const folderName = uuidv1() 
     return axios 
      .all([ 
       mkdir(folderName), 
       axios.get(url) 
      ]) 
      .then(axios.spread(function (f, r) { 
       return writeFile(path.join(__dirname, folderName, 'file.html'), r.data); 
      })); 
    } 

    return fetchPage() 
} 

Dann Sie es wie folgt verwenden würde:

downloadPage().then(() => { 
    // page is downloaded now 
}); 

Oder, in einer async Funktion können Sie tun:

await downloadPage(); 
// page is downloaded here 

Beachten Sie, dass ich mehrere Fälle von async und await entfernt habe, da sie nicht benötigt wurden. await fetchPage() hat dich am Ende von downloadPage() nicht gut gemacht. Von einem Zeitpunkt Sicht, die genau dasselbe wie return fetchPage() und auf diese Weise, Sie lösen tatsächlich mit dem aufgelösten Wert fetchPage(), die nützlicher sein kann. Es schien keinen Grund zu geben, async zu verwenden oder in downloadPage() zu warten. Beachten Sie, dass eine async-Funktion immer noch eine Zusage zurückgibt und der Aufrufer dieser Funktion weiterhin oder await für den Rückgabewert dieser Funktion verwenden muss. Wenn Sie await innerhalb von downloadPage() verwenden, ändert sich das für den Anrufer nicht.

Verwandte Themen