Async: Obteniendo un nuevo error al usar Async con Node 6.2.2 "Devolución de llamada ya llamada"

Creado en 27 jun. 2016  ·  12Comentarios  ·  Fuente: caolan/async

¿Qué versión de async estás usando?

3.9.5

¿En qué entorno ocurrió el problema (versión de nodo / versión del navegador)?

Nodo 6.2.2 y 5.0.71.52

¿Qué hiciste?

Esta aplicación

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

Qué esperabas que sucediera?

Que no me equivocaría

¿Cuál fue el resultado real?

Me estoy poniendo

/home/examples/public_html/learnnode2-examples/chap3/node_modules/async/dist/async.js:837
if (fn === null) throw new Error ("Ya se llamó a la devolución de llamada.");
^

Error: ya se llamó a la devolución de llamada.

La función de devolución de llamada en la siguiente sección del código

function loopFiles (archivos, devolución de llamada) {
files.forEach (función (nombre) {
devolución de llamada (nulo, nombre);
});
},

Se pierde en la segunda carrera.

Ejecuté este código con éxito a través de varias versiones de Node. Creo que probé esto cuando se lanzó Node 6 por primera vez.

En la segunda iteración, la función no es nula, pero algo está sucediendo en el código Async que genera este error.

question

Todos 12 comentarios

Porque llamaste a la devolución de llamada muchas veces aquí:

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

Utilice async.forEach para este caso.

Interesante. No he tenido problemas con versiones anteriores de Node y, de hecho, simplemente ejecuté esto con éxito en Node 6.0.0 en mi máquina Windows.

Entonces, algo ha cambiado entre 6.0.0 y 6.2.2 que hace que Async se rompa con el uso de forEach incorporado.

Solo un FYI, async.forEach no funciona. No se bloquea, pero no funciona.

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

Y, francamente, no estoy seguro de que sea el forEach el que causa el problema. Si lo estoy usando incorrectamente, avíseme.

Esta bien me rindo.

Actualicé mi máquina con Windows a 6.2.2 y este código funciona. Pero no funciona en mi máquina Linux. Ambos están construidos con el mismo motor V8. Ambos usan la misma versión de Async. Ambos tienen los mismos directorios de archivos de ejemplo.

En Linux, se produce un error. En Windows, no.

@shelleyp su cascada está estructurada incorrectamente para varios archivos. Creo que desea separarlo en dos cascadas o hacer que cada paso espere una matriz.

La razón por la que su cambio async.forEach no funcionó es porque no está llamando a la devolución loopFiles llamada (files, callback) => callback(null, files[0]) contrario, necesitará tener checkFiles , readData y modify esperar matrices (o crear una segunda cascada)

No voy a arreglar todo su código, pero así es como cambiaría su función checkFiles

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

....

Esta bien.

Solo sepa que esto funcionó hasta 6.2.2, por lo que cualquier cosa que haya causado que mi código no funcione puede hacer que el código de otras personas no funcione.

Extraño, lo único que debería hacer que el código funcione es si el readdir enumera
un archivo (también está roto para 0 archivos).

¿Le importaría verificar dos veces la salida de readdir en ambas versiones de nod?
El 27 de junio de 2016 a las 5:55 p.m., "Shelley Powers" [email protected] escribió:

Esta bien.

Solo sé que esto funcionó hasta 6.2.2, así que lo que sea que causó que mi código no
el trabajo puede hacer que el código de otras personas no funcione.

-
Recibe esto porque modificó el estado abierto / cerrado.
Responda a este correo electrónico directamente, véalo en GitHub
https://github.com/caolan/async/issues/1199#issuecomment -228887866, o silenciar
la amenaza
https://github.com/notifications/unsubscribe/ADUIEAfvkwCmdjmkIZIjipFGYgPQ6SzYks5qQEbpgaJpZM4I_Nsg
.

Este código siempre ha funcionado con varios archivos. Bueno, hasta 6.2.2 en Linux.

Pero acabo de comprobar en Windows. Sí, trabajó con cuatro archivos.

La salida de readdir es ['data1.txt', 'data2.txt', 'data3.txt', 'data4.txt']

La entrada a loopFiles es la misma.

En ese momento, con forEach, cada devolución de llamada obtiene un nombre de archivo individual.

Si alguna vez me hubiera encontrado con una pared de ladrillos con la matriz, no habría usado este enfoque. Pero siempre funcionó.

No es problema, siempre puedo actualizar el código para eliminar el manejo de la matriz. El problema real es que funciona en un entorno pero no en otro. Sin embargo, Node, V8 y Async son las mismas versiones.

Acabo de ejecutar un código ligeramente modificado en Ubuntu 16.04 en el nodo 6.0.0 y 6.2.2. En ambos casos obtuve el mismo resultado:

  • data1.txt, devolución de llamada para el primer elemento (data1.txt)
  • Error: ya se llamó a la devolución de llamada

Guión modificado:

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

Pero no lo probaste en Windows.

Claro, lo estoy cerrando porque no es un problema asincrónico.

El lunes 27 de junio de 2016 a las 8:20 p.m., Shelley Powers [email protected]
escribió:

Pero no lo probaste en Windows.

-
Recibe esto porque modificó el estado abierto / cerrado.
Responda a este correo electrónico directamente, véalo en GitHub
https://github.com/caolan/async/issues/1199#issuecomment -228914233, o silenciar
la amenaza
https://github.com/notifications/unsubscribe/ADUIEDNwRmcEjcAnVmSCHBBIHvdM6DL3ks5qQGiwgaJpZM4I_Nsg
.

¿Fue útil esta página
0 / 5 - 0 calificaciones