更改javascript函数的参数/" class"异步?

时间:2016-03-26 21:33:18

标签: javascript node.js asynchronous attributes

所以我有一些JS代码,我理想的是希望作为自定义"对象"但由于JS的性质,我似乎无法这样做。

所以我在网上的某个博客上写了这篇文章(在我看来这是优雅的,但可能不是')#

var mongoose = require('mongoose');
var dbservice = function () {
    this.connected = false;
    this.connection_error = false;
    this.status_messages = [];
    this.connect = function() {
        mongoose.connect('Laaaadeedaaaa');
        var db = mongoose.connection;
        db.on('error', function() {
            this.status_messages.push('Nooo! Connection Error');
            console.error.bind(console, 'Nooo! Connection Error: ');
            this.connection_error = true;  
        });
        db.once('open', function() {
            this.status_messages.push('Successfully connected to the database!');
            console.log('Successfully connected to the database!');
            this.connected = true;
        });
    };
    //DB (db.runCommand({whatsmyuri: 1}))
    this.createUser = function(user_in, password_in) {
        require("./data/models/user");
        var User = mongoose.model('User');
        var newUser = new User({ username: user_in, password: password_in, date_created: Date() });
        newUser.save(function(err, data) {
            if (err) {
                this.status_messages.push('User creation error!');
                console.log(err);
            }
            else {
                this.status_messages.push('Success!');
                console.log('Success:', data);
            }
        });
    };
};
module.exports = dbservice;

我试着这样称呼:

var cur_service = new dbservice();
cur_service.connect();
setTimeout(function() { 
    console.log("Connected!");
    console.log(cur_service.connected);
},3000);

所以本质上发生的是this.connect成功运行(yay)并且它自己快速完成(因为mongoose函数是异步的)。大约1秒后,控制台按预期输出Successfully connected to the database。但是,当计时器滴答时,cur_service.connected仍然是假的,这使我感到困惑,因为我已将其设置为真并且异步功能已完全完成。这意味着this.blah =格式在异步返回时不合适。那你怎么解决这个问题呢?还有其他基本的语法错误,我没有注意到吗?我刚刚开始js开发(只做过iOS / Desktop / C ++),所以这一切都是新的和抽象的:P

感谢帮助人员!

1 个答案:

答案 0 :(得分:1)

回调函数通常与父作用域没有相同的this值。有很多方法可以解决这个问题,但一种简单的方法是将this值保存在名为self之类的父作用域变量中,然后从回调中引用self而不是引用this。这方面的一个例子是:

var mongoose = require('mongoose');
var dbservice = function () {
    var self = this;
    this.connected = false;
    this.connection_error = false;
    this.status_messages = [];
    this.connect = function(cb) {
        mongoose.connect('Laaaadeedaaaa');
        var db = mongoose.connection;
        db.on('error', function(err) {
            // use self in here to reference the parent object
            self.status_messages.push('Nooo! Connection Error');
            console.error.bind(console, 'Nooo! Connection Error: ');
            self.connection_error = true;  
            callback(err);
        });
        db.once('open', function() {
            self.status_messages.push('Successfully connected to the database!');
            console.log('Successfully connected to the database!');
            self.connected = true;
            // signal completion of the connection
            callback(null);
        });
    };
    //DB (db.runCommand({whatsmyuri: 1}))
    this.createUser = function(user_in, password_in, callback) {
        var self = this;
        require("./data/models/user");
        var User = mongoose.model('User');
        var newUser = new User({ username: user_in, password: password_in, date_created: Date() });
        newUser.save(function(err, data) {
            if (err) {
                self.status_messages.push('User creation error!');
                console.log(err);
            }
            else {
                self.status_messages.push('Success!');
                console.log('Success:', data);
            }
            callback(err, data);
        });
    };
};
module.exports = dbservice;

通常,我认为您希望将异步结果作为完成回调的参数进行通信,而不是作为对象状态。这是因为您不知道何时设置了对象状态。您只知道当调用完成回调时,您可以将其作为回调传递给回调,如上所示。

只有在调用dbservice时实例化新对象(例如:

)时,这才有效
var dbservice = require('dbservice');
var d = new dbservice();
d.connect(function(err) {
   if (!err) {
        d.createUser("bob", "password", function(err) {
            if (!err) {
                // user created here
            }
        });
     }
});

你在这里遇到的另一个问题是你应该使用回调或promise来表示异步操作的结束,而不是定时器猜测操作何时完成。我已经为您现有的代码添加了一些回调以向您展示一般概念,但您还必须努力正确地返回错误。

如果你真的要写这么多异步代码,你真的想学习如何使用promises,因为一旦你宣传你的接口,它们会使异步链接和错误处理变得更容易(这意味着转换他们返回承诺而不是直接回调)并学习如何使用承诺来获得最大利益。