所以我有一些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
感谢帮助人员!
答案 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,因为一旦你宣传你的接口,它们会使异步链接和错误处理变得更容易(这意味着转换他们返回承诺而不是直接回调)并学习如何使用承诺来获得最大利益。