2012-02-07 2 views
1

Я не могу понять, почему выборки функция не возвращает информацию, которую я хотел бы иметь:объект не возвращает нужный объект в Javascript

(function(){ 
    var root = this; 
    var Database = root.Database = {}; 

    var Db = require('mongodb').Db, 
    Connection = require('mongodb').Connection, 
    Server = require('mongodb').Server; 

    var host = process.env['MONGO_NODE_DRIVER_HOST'] != null ? process.env['MONGO_NODE_DRIVER_HOST'] : 'localhost'; 
    var port = process.env['MONGO_NODE_DRIVER_PORT'] != null ? process.env['MONGO_NODE_DRIVER_PORT'] : Connection.DEFAULT_PORT; 

    // Require Underscore, if we're on the server, and it's not already present. 
    var _ = root._; 
    if (!_ && (typeof require !== 'undefined')) _ = require('./underscore'); 



    Database.ActiveRecord = function(attributes, collection){ 
     this.collection = collection; 
     this.cid = _.uniqueId('c'); 
     attributes || (attributes = {}); 
     this.attributes = attributes; 
    }; 

    // Connecting to database and setting the connection as a shared variable among ActiveRecords 
    console.log("Connecting to " + host + ":" + port); 

    Database.ActiveRecord.prototype.db = new Db('node-mongo-eslip', new Server(host, port, {})); 

    _.extend(Database.ActiveRecord.prototype, { 

     initialize: function(){}, 

     // Returns `true` if the attribute contains a value that is not null 
     // or undefined. 
     has: function(attr) { 
      return this.attributes[attr] != null; 
     }, 

     // Sets attributes 
     set: function(key, value){ 
      var attrs, attr, val; 
      if(_.isObject(key) || key == null){ 
       throw Error("The key should not be an object or null"); 
      }else{ 
       attrs = {}; 
       attrs[key] = value; 
      } 

      if (!attrs) return this; 

      var now = this.attributes; 

      for(attr in attrs){ 
       val = attrs[attr]; 
       if(!_.isEqual(now[attr], val)) now[attr] = val; 
      } 
     }, 

     unset: function(key){ 
      return this.set(attr, null); 
     }, 

     toJSON: function() { 
      return _.clone(this.attributes); 
     }, 

     fetch: function(query, fields, options){ 
      var record = this; 
      record.db.open(function(err, db){ 
       if(!(record.collection||(typeof record.collection === 'string'))) throw Error('You should define a name attribute, which represents the collection of the Database'); 
       db.collection(record.collection, function(err, collection){ 
        console.log('Fetching...'); 
        collection.find(query, fields, options).toArray(function(err, docs) { 
         return docs; 
        }); 
       }); 
      }); 
     }, 

     save: function(){ 
      var record = this; 
      record.db.open(function(err, db){ 
       if(!(record.collection||(typeof record.collection === 'string'))) throw Error('You should define a name attribute, which represents the collection of the Database'); 
       db.collection(record.collection, function(err, collection){ 
        collection.insert(_.clone(record.attributes), {safe:true}, 
        function(err, objects) { 
         if (err) console.warn(err.message); 
         if (err && err.message.indexOf('E11000 ') !== -1) { 
          console.log('This id has already been inserted into the database'); 
         } 
        }); 
       }); 
       console.log('Saved!'); 
      }); 
     } 
    }); 
}()); 

Я потратить некоторое время, пытаясь выяснить, что отсутствует, и не сделал этого, может быть, у кого-то были бы лучшие шансы разобраться.

+2

Добро пожаловать в удивительный мир ** асинхронном **! Вы не можете этого сделать. – SLaks

+0

Да, теперь имеет смысл – mabounassif

ответ

1

К тому времени, когда выполняется функция обратного вызова, с которой вы пытаетесь запустить return docs, внешняя функция fetch уже вернулась - как предложено @SLaks, добро пожаловать в прекрасный мир асинхронного программирования.

Обещания могут быть отличным способом для работы с асинхронным кодом - они доступны в jQuery, Dojo и других библиотеках и инструментариях. Ваш метод fetch может вернуть обещание, и код, который вызвал метод fetch, мог бы реагировать, когда возвращенное обещание было «разрешено». Вот как это выглядит с Dojo:

fetch: function(query, fields, options){ 
     var record = this, dfd = new dojo.Deferred; 

     record.db.open(function(err, db){ 
      if(!(record.collection||(typeof record.collection === 'string'))) throw Error('You should define a name attribute, which represents the collection of the Database'); 
      db.collection(record.collection, function(err, collection){ 
       console.log('Fetching...'); 
       collection.find(query, fields, options).toArray(function(err, docs) { 
        dfd.resolve(docs); 
       }); 
      }); 
     }); 

     return dfd.promise; 
    }, 

Затем код, который называется выборки может выглядеть следующим образом:

myDB.fetch().then(function(docs) { 
    // do whatever you need with the docs 
}); 
+0

Я фактически изменил функцию выборки, чтобы она поддерживала функцию обратного вызова. Сейчас он работает отлично. http://howtonode.org/express-mongodb был моей ссылкой для нуждающихся. – mabounassif

1

Вы не можете этого сделать, потому что в JS выражение функции return XXXX; означает, что поток управления возвращается к внешней функции. Например:

(function(){ 
    function foo(){ 
     return "inner"; 
    } 
    foo(); 
})(); 

Внешняя функция действительно ничего не возвращает. Поскольку функция foo просто возвращает поток управления внешней функции без информации «внутреннего».

Если вы хотите что-то вернуть, переместите его в область внешней функции. Это вернет то, что вы хотите.

Надеюсь, это поможет.

Смежные вопросы