现在,我的 try/catch block 是否能正常工作对我来说还是个谜。我围绕代码设置它们,然后,因为代码中的某些内容是“异步的”,这似乎是在操作系统级别 fork 到另一个线程/进程的一种奇特方式,如果 try/catch 发生在其中,则会被忽略代码。
我对此很好,我只是想知道是否有一些迹象表明这一点?按照惯例,我明白,如果一个电话要求回调,它是异步的,否则不是。我明白为什么回调意味着异步,但恐怕反过来并不总是正确的:没有什么能阻止我用一个 try/catch 包围一个调用,它被加载到一个新的调用堆栈中,也不会要求回调。这对我来说似乎真的很困惑,如果可能的话,我希望对我的 try/catches 有更多的控制,而不是使用所有未捕获的异常都由其处理的默认回调。
- 是否有语义来告诉我代码何时离开 当前堆栈?
更新:这是一个例子:
var UserSchema = new mongoose.Schema({
email: {type: String, unique: true},
password: String,
firstName: String,
lastName: String,
created_at: {type: Date, default: Date.now},
updated_at: Date
});
var User = mongoose.model('User', UserSchema);
var users = [
{email: 'foo@bar.com', firstName: 'Justin', lastName: 'Jones'},
{email: 'foo@bar.com', firstName: 'Justin', lastName: 'Jones'}
];
users.forEach(function(user) {
var newUser = new User(user);
newUser.save(function(err, obj) {
if (!err) console.log("Saved: ", obj.email);
});
});
鉴于上面的代码,无法在 save() 内部捕获异常,因为它发生在另一个调用堆栈中。有没有什么办法可以让我从外部知道调用 save() 时会发生什么?
更新:每个告诉我为此使用处理程序的人都应该阅读 this ?它明确建议不要处理未在其“线程执行”中捕获的异常,因为它仅充当线程。
最佳答案
“异步”不是“ fork 到另一个线程/进程的奇特说法”。
JavaScript 是单线程的。故事结局。在语言层面没有 fork 。
“异步”的意思就是它所说的:执行顺序不是代码的顺序。一些代码——回调函数——将在特定事件发生时的某个时间点执行。它是一种基于事件的编程模型。
考虑这个简单的例子:
function hello () { alert("Hello!"); }
setTimeout(hello, 2000);
这是最基本形式的异步回调。您有一个回调处理程序 - 函数 hello
- 和一个事件生成器,在本例中是一个基于时间的生成器。
一旦事件发生(已经过了 2 秒),就会调用回调处理程序。
现在进行修改:
function hello() { alert(foo.bar); }
try {
setTimeout(hello, 2000);
} catch (ex) {
alert(ex.message);
}
我们围绕 setTimeout
引入了一个 try-catch block 。它保护回调的注册,仅此而已。这一步很可能会成功,因此 try-catch block 永远不会做任何事情。回调本身 将在 2 秒后失败这一事实自然不会影响 try-catch block 。这是您感到困惑的行为。
现在进行另一个修改:
function hello() {
try {
alert(foo.bar);
} catch (ex) {
alert("foo.bar is not defined");
}
}
setTimeout(hello, 2000);
现在 try-catch block 保护实际上可能失败的步骤。这意味着您必须在可能发生错误的地方使用 try-catch block ,而不是通常将它们包裹在程序的大部分周围(这似乎是您所做的)。
但是如何获得异常来做一些有用的和可配置的事情呢?自然地,通过引入更多回调。
function hello(onError) {
try {
alert(foo.bar);
} catch (ex) {
onError("foo.bar is not defined", ex);
}
}
function errorHandler(customMessage, exception) {
alert(customMessage);
// or do something with exception
}
setTimeout(function () {
hello(errorHandler)
}, 2000);
根据您添加的示例:
var saveUsers = function(users, onSuccess, onError) {
users.forEach(function(user) {
var newUser = new User(user);
newUser.save(function(err, obj) {
if (err) {
onError(err, obj);
return false;
} else {
onSuccess(obj);
}
});
});
}
var users = [
{email: 'foo@bar.com', firstName: 'Justin', lastName: 'J'},
{email: 'foo@bar.com', firstName: 'Justin', lastName: 'J'}
];
saveUsers(
users,
function (user) { console.log("Saved: ", user.email); },
function (err, user) { console.log("Could not save: ", user.email); }
});
关于javascript - 使用 Node.js,是否有一些语义可以告诉我代码何时要离开当前堆栈?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10304634/