Async: Neuer Fehler bei Verwendung von Async mit Node 6.2.2 "Rückruf bereits angerufen"

Erstellt am 27. Juni 2016  ·  12Kommentare  ·  Quelle: caolan/async

Welche Version von Async verwendest du?

3.9.5

In welcher Umgebung trat das Problem auf (Knotenversion/Browserversion)

Knoten 6.2.2 und 5.0.71.52

Was haben Sie gemacht?

Diese App

var fs = require('fs'),
    async = require('async'),
    _dir = './data/';

var writeStream = fs.createWriteStream('./log.txt',
      {'flags' : 'a',
       'encoding' : 'utf8',
       'mode' : 0666});

async.waterfall([
   function readDir(callback) {
      fs.readdir(_dir, function(err, files) {
         callback(err,files);
      });
   },
   function loopFiles(files, callback) {
      files.forEach(function (name) {
         callback (null, name);
      });
   },

   function checkFile(file, callback) {
      fs.stat(_dir + file, function(err, stats) {
         callback(err, stats, file);
      });
   },
   function readData(stats, file, callback) {
      if (stats.isFile())
         fs.readFile(_dir + file, 'utf8', function(err, data){
           callback(err,file,data);
       });
   },
   function modify(file, text, callback) {
      var adjdata=text.replace(/somecompany\.com/g,'burningbird.net');
      callback(null, file, adjdata);
   },
   function writeData(file, text, callback) {
       fs.writeFile(_dir + file, text, function(err) {
          callback(err,file);
       });
   },

   function logChange(file, callback) {
       writeStream.write('changed ' + file + '\n', 'utf8',
                       function(err) {
          callback(err);
      });
   }
], function (err) {
         if (err) {
            console.log(err.message);
         } else {
            console.log('modified files');
         }
});

Was haben Sie erwartet?

Dass ich keinen Fehler bekomme

Was war das tatsächliche Ergebnis?

Ich erhalte

/home/examples/public_html/learnnode2-examples/chap3/node_modules/async/dist/async.js:837
if (fn === null) throw new Error("Callback wurde bereits aufgerufen.");
^

Fehler: Callback wurde bereits angerufen.

Die Callback-Funktion im folgenden Abschnitt des Codes

Funktion loopFiles(Dateien, Rückruf) {
files.forEach(Funktion (Name) {
Rückruf (null, Name);
});
},

Geht im zweiten Lauf verloren.

Ich habe diesen Code erfolgreich durch mehrere Versionen von Node. Ich glaube, ich habe dies getestet, als Node 6 zum ersten Mal veröffentlicht wurde.

In der zweiten Iteration ist die Funktion nicht null, aber im Async-Code passiert etwas, was zu diesem Fehler führt.

question

Alle 12 Kommentare

Weil du hier oft den Rückruf angerufen hast:

function loopFiles(files, callback) {
    files.forEach(function(name) {
        callback(null, name);
    });
},

Bitte verwenden Sie in diesem Fall async.forEach.

Interessant. Ich hatte keine Probleme mit früheren Versionen von Node und habe dies gerade erfolgreich in Node 6.0.0 auf meinem Windows-Rechner ausgeführt.

Zwischen 6.0.0 und 6.2.2 hat sich also etwas geändert, was dazu führt, dass Async mit der Verwendung von integriertem forEach bricht.

Nur ein FYI, async.forEach funktioniert nicht. Es stürzt nicht ab, aber es funktioniert nicht.

   function loopFiles(files, callback) {
      async.forEach(files, function (name, callback) {
         callback (null, name);
      });
   },

Und ehrlich gesagt bin ich mir nicht sicher, ob es das forEach ist, das das Problem verursacht. Wenn ich es falsch verwende, lass es mich wissen.

OK ich gebe auf.

Ich habe meinen Windows-Rechner auf 6.2.2 aktualisiert und dieser Code funktioniert. Aber es funktioniert nicht auf meinem Linux-Rechner. Beide basieren auf dem gleichen V8-Motor. Beide verwenden dieselbe Version von Async. Beide haben dieselben Beispieldateiverzeichnisse.

Unter Linux wird ein Fehler ausgegeben. Unter Windows nicht.

@shelleyp Ihr Wasserfall ist für mehrere Dateien falsch strukturiert. Ich denke, Sie möchten es in zwei Wasserfälle aufteilen oder jeden Schritt ein Array erwarten lassen.

Der Grund, warum Ihre Änderung von async.forEach nicht funktioniert hat, ist, dass Sie den Rückruf von loopFiles nicht aufrufen. Diese Funktion macht sowieso nicht das, was Sie wollen, wenn Sie nur die erste Datei verarbeiten möchten, ändern Sie loopFiles in (files, callback) => callback(null, files[0]) andernfalls benötigen Sie checkFiles , readData und modify erwarten Arrays (oder erstellen einen zweiten Wasserfall)

Ich werde nicht Ihren gesamten Code korrigieren, aber so würde ich Ihre checkFiles Funktion ändern

async.waterfall([
   function readDir(callback) {
      fs.readdir(_dir, callback);
   },

   function checkFile(files, callback) {
      async.map(files, (file, cb) => {
         fs.stat(_dir + file, function(err, stats) {
            cb(err, {stat: stats, file: file});
         });
      }, (err, stats) => {
         callback(err, stats);
      });
   },

....

Das ist in Ordnung.

Wissen Sie nur, dass dies bis 6.2.2 funktioniert hat, was auch immer dazu geführt hat, dass mein Code nicht funktioniert, kann dazu führen, dass der Code anderer Leute nicht funktioniert.

Seltsamerweise sollte dieser Code nur funktionieren, wenn die readdir-Listen
eine Datei (sie ist auch bei 0 Dateien defekt).

Macht es Ihnen etwas aus, die Ausgabe von readdir in beiden Versionen von nod . zu überprüfen?
Am 27. Juni 2016 um 17:55 Uhr schrieb "Shelley Powers" [email protected] :

Das ist in Ordnung.

Wissen Sie nur, dass dies bis 6.2.2 funktioniert hat, was auch immer dazu führte, dass mein Code nicht funktionierte
Arbeit kann dazu führen, dass der Code anderer Personen nicht funktioniert.


Sie erhalten dies, weil Sie den Status Öffnen/Schließen geändert haben.
Antworten Sie direkt auf diese E-Mail und zeigen Sie sie auf GitHub an
https://github.com/caolan/async/issues/1199#issuecomment -228887866 oder stumm
der Faden
https://github.com/notifications/unsubscribe/ADUIEAfvkwCmdjmkIZIjipFGYgPQ6SzYks5qQEbpgaJpZM4I_Nsg
.

Dieser Code hat immer mit mehreren Dateien funktioniert. Nun, bis 6.2.2 unter Linux.

Aber gerade unter Windows überprüft. Yup, mit vier Dateien gearbeitet.

Ausgabe von readdir ist [ 'data1.txt', 'data2.txt', 'data3.txt', 'data4.txt' ]

Eingabe zu loopFiles ist die gleiche.

Zu diesem Zeitpunkt erhält mit forEach jeder Callback einen individuellen Dateinamen.

Wäre ich jemals mit dem Array gegen eine Mauer gestoßen, hätte ich diesen Ansatz nicht verwendet. Aber es hat immer funktioniert.

Kein Problem, ich kann den Code jederzeit aktualisieren, um die Array-Behandlung zu entfernen. Das eigentliche Problem ist, dass es in einer Umgebung funktioniert, in einer anderen jedoch nicht. Node, V8 und Async sind jedoch die gleichen Versionen.

Ich habe gerade leicht modifizierten Code in Ubuntu 16.04 in den Knoten 6.0.0 und 6.2.2 ausgeführt. In beiden Fällen habe ich die gleiche Ausgabe erhalten:

  • data1.txt, Rückruf für das erste Element (data1.txt)
  • Fehler: Rückruf wurde bereits angerufen

Geändertes Skript:

var fs = require('fs'),
    async = require('async'),
    _dir = './data/';

async.waterfall([
   function readDir(callback) {
      fs.readdir(_dir, callback);
   },
   function loopFiles(files, callback) {
      files.forEach(function (name) {
         callback (null, name);
      });
   },
   console.log.bind(console)
], console.error)
$ ls data
> data1.txt  data2.txt

Aber Sie haben es nicht in Windows versucht.

Sicher, ich schließe es als kein asynchrones Problem.

Am Montag, 27. Juni 2016 um 20:20 Uhr, Shelley Powers [email protected]
schrieb:

Aber Sie haben es nicht in Windows versucht.


Sie erhalten dies, weil Sie den Status Öffnen/Schließen geändert haben.
Antworten Sie direkt auf diese E-Mail und zeigen Sie sie auf GitHub an
https://github.com/caolan/async/issues/1199#issuecomment -228914233 oder stumm
der Faden
https://github.com/notifications/unsubscribe/ADUIEDNwRmcEjcAnVmSCHBBIHvdM6DL3ks5qQGiwgaJpZM4I_Nsg
.

War diese Seite hilfreich?
0 / 5 - 0 Bewertungen