Nodejs 使用then写异步导致逻辑问题
Nodejs 使用then写异步导致逻辑问题
238 AdminUser.findByName(name)
239 .then(function(model){
240 if(!model || model.passwd != passwd){
241 res.send(“fail”);
242 throw new GError(“用户名或密码不正确”);
243 }
244 return model;
245 })
246 .then(function(model){
247 status = model.updatePass(newPasswd);
248 return status;
249 });
250 })
251 .then(function(status){
252 console.log(“status:”+status);
253 res.send(status);
254 })
按照本应该的逻辑,247行更改密码后,将更改是否成功的状态用变量status传回来,给251行的then,然后这个then根据status来渲染网页。
但是由于247行的数据库操作是一个耗时的异步操作,所以251行的function会在247行的数据库操作结束之前执行。结果就是status还没有获得值就return给了渲染操作(252行会打印出status:undefined)。想了几个方法都没有成功,不知道大家有什么方法能解决这个问题。
Node.js 使用 then
写异步导致逻辑问题
在 Node.js 中使用 .then()
方法处理异步操作时,可能会遇到一些逻辑问题,特别是当多个异步操作需要按顺序执行时。以下是一个具体的例子,展示了如何通过改进代码结构来解决这些问题。
示例代码
AdminUser.findByName(name)
.then(function(model) {
if (!model || model.passwd !== passwd) {
res.send("fail");
throw new GError("用户名或密码不正确");
}
return model;
})
.then(function(model) {
// 这里需要等待 updatePass 方法完成后再继续
return model.updatePass(newPasswd).then(function(status) {
return status;
});
})
.then(function(status) {
console.log("status:" + status);
res.send(status);
})
.catch(function(error) {
console.error(error);
res.status(500).send("服务器错误");
});
解释
-
第一个
then
:- 首先,我们查找用户信息。
- 如果用户不存在或密码不匹配,则返回错误并终止链式调用。
-
第二个
then
:- 在这里,我们需要确保
updatePass
方法完成后再继续。 updatePass
方法本身返回一个 Promise,所以我们需要在这个 Promise 上再加一层.then()
来获取更新后的状态。
- 在这里,我们需要确保
-
第三个
then
:- 最后,我们将获取到的状态传递给下一个
then
,并根据这个状态进行相应的处理。
- 最后,我们将获取到的状态传递给下一个
-
catch
:- 添加一个全局的
.catch()
来捕获任何可能发生的错误,并进行适当的处理。
- 添加一个全局的
通过这种方式,我们可以确保每个异步操作都按顺序执行,并且每个操作的结果都能被正确地传递到下一个操作中。这样可以避免 status
为 undefined
的问题。
你的代码写的很有问题,不仅冗余而且没有用对。 updatePass必须也要返回一个Promise,否则这个异步操作还没执行,下一个then方法就执行了。 所以status肯定不是预期的返回值。 还有第244行没有必要再返回一次,多加一个then,把updatePass改造下直接这样
244 return model. updatePass(newPasswd)
另外,看你的似乎用的是mongoose,如果是可以看下我的mongoomise
恩,对异步还是很不适应和熟悉。
如您所说的,直接改成
return model. updatePass(newPasswd)
结果还是一样,在updatePass还没有执行完的时候,已经执行了252行的console语句。
另外,我这儿用的是sequelize来连接mysql数据库。
你的问题在于,updatePass
方法可能也是一个返回 Promise 的异步操作,但你在处理时没有等待它完成。因此,你需要确保 updatePass
的异步操作完成后再进行下一步。
你可以使用 .then
来确保每个异步操作都按顺序完成。以下是修改后的代码:
AdminUser.findByName(name)
.then(function(model) {
if (!model || model.passwd !== passwd) {
res.send("fail");
throw new GError("用户名或密码不正确");
}
return model;
})
.then(function(model) {
// 确保 updatePass 返回的是一个 Promise
return model.updatePass(newPasswd).then(function(status) {
return { model, status };
});
})
.then(function(result) {
const { model, status } = result;
console.log("status:" + status);
res.send(status);
})
.catch(function(error) {
console.error(error);
res.status(500).send("Internal Server Error");
});
解释:
- 第一个
then
:检查用户名和密码是否正确。 - 第二个
then
:调用updatePass
方法,并等待其完成。updatePass
应该返回一个 Promise,我们通过.then
来捕获其结果并返回一个新的对象{ model, status }
。 - 第三个
then
:接收上一步的结果,解构出model
和status
,然后打印并发送status
。 catch
:捕捉任何错误并返回一个错误响应。
这样可以确保所有异步操作按顺序执行,避免了提前返回未完成的操作。