admin管理员组文章数量:1392076
I'm using a Mongoose query like this:
let Value = 'START'
myCollection.findOne({param:Value}) .then((doc) => {
if (!doc) {
// In this case no document found on my collection.
// I need to log this case with the parameter 'Value' used for the query.
// In my example it should be 'START'.
log(Value) // => Sometimes Value is 'END' due to the asyn and the query delay.
}
})
Value = 'END'
Sometime, my query return no value. This is not an error but I need to log the query in this case. Unfortunately, the doc parameter is null. Because it is run async, the "Value" has changed when I enter the then function and I cannot use my "Value" variable.
How can I get the param value inside the then function ?
I'm using a Mongoose query like this:
let Value = 'START'
myCollection.findOne({param:Value}) .then((doc) => {
if (!doc) {
// In this case no document found on my collection.
// I need to log this case with the parameter 'Value' used for the query.
// In my example it should be 'START'.
log(Value) // => Sometimes Value is 'END' due to the asyn and the query delay.
}
})
Value = 'END'
Sometime, my query return no value. This is not an error but I need to log the query in this case. Unfortunately, the doc parameter is null. Because it is run async, the "Value" has changed when I enter the then function and I cannot use my "Value" variable.
How can I get the param value inside the then function ?
Share Improve this question edited Mar 13 at 8:47 DarkBee 15.5k8 gold badges72 silver badges118 bronze badges asked Mar 11 at 16:54 DarkScytaleDarkScytale 11 bronze badge 2 |2 Answers
Reset to default 0Asynchronous JavaScript functions such as your myCollection.findOne
stop the blocking of the Node.js
single thread and allows it to continue execution of the code in your script. This is a big topic that you should spend time reading and learning. That means your Value = 'END'
was executed before the result of your database query was returned. The JavaScript engine continued to execute synchronous code you had in the lines immediately after the then
function. So when you actually come to logging the value with log(Value)
, the value of Value
was already reassigned to 'END'
.
When you read your code you are reading it line by line and intuitively you see that log(Value)
is above the Value = 'END'
so how can it have changed already?
To keep things simple, your myCollection.findOne
has to issue a network request to the server running your database, query the database, then return the results back across the network to your server. That might involve disk I/O and a high latency network which all takes time. Asynchronous functions allow you delegate that execution similar to giving your order to a waiter. The waiter can send that order to the kitchen and continue serving you drinks. The kitchen will let the waiter know when your order is ready and bring it to you. You shouldn't have to wait for your food before you enjoy your drink . The then()
block is like the kitchen telling the waiter the order is ready. By which time you have different drink than the one you had when you placed the order.
There is an alternative pattern to using then
blocks and that is async/await
. In this case using the await
keyword before the myCollection.findOne
tells the JavaScript engine to pause execution of the rest of the code in your script until the the request is settled (fulfilled or rejected). So essentially I'm happy to wait for my food order on this occasion as the rest of my evening depends on it. Crucially though it also doesn't block the Node.js
single thread and carries on responding to requests - just not those lines of code directly after the await myCollection.findOne
. Again, it's a very large topic involving promises and error handling that I won't go into.
1. Solution with then()
:
let Value = 'START'
const valueSaved = Value;
myCollection.findOne({param:Value}).then((doc) => {
if (!doc) {
console.log(valueSaved)
// 'START'
}
})
Value = 'END'
Simply assign Value
to another variable which you then reference inside the then()
block.
2. Solution with async/await
:
app.get('/', async (req, res) => { //< function must be async
try {
let Value = 'START';
const doc = await myCollection.findOne({param:Value}); //< use await here
// Code will not continue until settled
// ...
if(!doc){
console.log(Value)
}
let Value = 'END';
res.status(200).json({
doc: doc
});
} catch(err) {
console.log(err)
res.status(500).json({
msg: 'Error on server'
});
}
});
The await
keyword must be used inside a function that is marked as async
such as the callback to a router etc. (top-level await
also possible)
The issue is due to JavaScript's asynchronous nature. When the .findOne()
query executes, the value of Value
might have already changed before the .then()
callback runs.
To preserve the value of Value
at the time of the query, you need to capture it within the .findOne()
call:
let Value = 'START';
myCollection.findOne({ param: Value }).then((doc) => {
if (!doc) {
console.log(`No document found for query: ${Value}`);
}
});
Value = 'END';
本文标签: nodejsHow to get the query from the then functionStack Overflow
版权声明:本文标题:node.js - How to get the query from the then function? - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1744781297a2624730.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
async/await
pattern or by moving the reassignment ofValue
into the thethen
block. Someone can give you a "make it work" answer but can you explain whyValue
is being set toEND
? That might help someone give you an answer with more meaning. – jQueeny Commented Mar 11 at 20:14