在nodejs中已经调用异步瀑布回调错误

时间:2017-08-23 16:43:19

标签: node.js callback waterfall

我是nodejs的新手。我一直在摸不着为什么下面的代码抛出错误。我发现一些类似的堆栈溢出,但无法帮助找到错误。

var albums_coll,photos_coll;    
    async.waterfall([
      function(cb){
        MongoClient.connect(url,
         (err,dbase)=>{
          if(err) {
            console.log('bad');
            process.exit(-1);
          }
          console.log("I have a connection!");
          db=dbase;
          cb(null);
        }
        );
      },

      function(cb){
        db.collection("albums",cb);
      },

      function(album_obj,cb){
        albums_coll = album_obj;
      db.collection("photos",cb);
    },

    function(photos_obj,cb){
      photos_coll = photos_obj;
      cb(null);

    },

    function(cb){
      albums_coll.InsertOne(a1,cb);
    },
    function(inserted_doc,cb){
      console.log("I have Inserted a document!!");
      console.log(inserted_doc);
      cb(null);
    }
    ],
    function(err,results){
      console.log("Done!!!");
      console.log(err);
      console.log(results);
      db.close();
    });

请建议!!

以下是它显示的错误。

I have a connection!
C:\Users\thathine\NodeLive\Chapter08\mongotest\node_modules\mongodb\lib\mongo_client.js:433
          throw err
          ^

Error: Callback was already called.
    at C:\Users\thathine\NodeLive\Chapter08\mongotest\node_modules\async\dist\async.js:903:32
    at Db.collection (C:\Users\thathine\NodeLive\Chapter08\mongotest\node_modules\mongodb\lib\db.js:466:27)
      .
      .           
      .

1 个答案:

答案 0 :(得分:0)

您传入callback()功能的db.collection()功能被称为两次。第一次发生这种情况是在 MongoDB库内部,同时调用db.collection()。它发生在下面的块中 - 我添加了一个注释,指向第466行,如堆栈中所示:

if(options == null || !options.strict) {
    try {
      var collection = new Collection(this, this.s.topology, this.s.databaseName, name, this.s.pkFactory, options);
      if(callback) callback(null, collection);
      return collection;
    } catch(err) {
      // if(err instanceof MongoError && callback) return callback(err);
      if(callback) return callback(err);  // <-- Line 466 - first time callback is called
      throw err;
    }
  }

第二次被调用时,是异步库需要确定它是否必须执行数组中的下一个任务或调用最终回调;到那时,回调已经为空。您所看到的错误是在异步库onlyOnce()函数中引发的:

function onlyOnce(fn) {
    return function() {
        if (fn === null) throw new Error("Callback was already called.");
        var callFn = fn;
        fn = null;
        callFn.apply(this, arguments);
    };
}

因此,以下代码将引发错误:

async.waterfall([
    function(callback) {
        MongoClient.connect('mongodb://localhost:27017/test', (error, db) => {
            if (error) {
                console.error(error);
                process.exit(-1);
            }
            callback(null, db);
        });
    },
    function(db, callback) {
        console.log('Querying albums collection...');

        // This will cause the exception
        db.collection('albums', callback);
    },
    function(db, albums, callback) {
        console.log('Got albums...');
        console.log('Querying photos collection...');

        db.collection('photos', (error, photos) => {
            if (error) {
                return callback(error);
            }

            callback(null, db, albums, photos);
        });
    },
    function(db, albums, photos, callback) {
        console.log('Got photos...');

        callback(null, 'DONE');
    }
], function (error, results) {
    console.error(error);
    console.log(results);

    process.exit(0);
});

虽然此版本的代码将按预期执行:

async.waterfall([
    function(callback) {
        MongoClient.connect('mongodb://localhost:27017/test', (error, db) => {
            if (error) {
                console.error(error);
                process.exit(-1);
            }
            callback(null, db);
        });
    },
    function(db, callback) {
        console.log('Querying albums collection...');

        db.collection('albums', (error, albums) => {
            if (error) {
                return callback(error);
            }

            callback(null, db, albums);
        });
    },
    function(db, albums, callback) {
        console.log('Got albums...');
        console.log('Querying photos collection...');

        db.collection('photos', (error, photos) => {
            if (error) {
                return callback(error);
            }

            callback(null, db, albums, photos);
        });
    },
    function(db, albums, photos, callback) {
        console.log('Got photos...');

        callback(null, 'DONE');
    }
], function (error, results) {
    console.error(error);
    console.log(results);

    process.exit(0);
});
/* Output:
Querying albums collection...
Got albums...
Querying photos collection...
Got photos...
null
DONE
*/

希望这有帮助!