Below have I pasted in PoC code, where I have removed lots of lines, but it shows the problem/question I am facing.
createPost()
returns a "post number" in the ret
variable. I don't need the "post number for anything else than logging it.
With the current implementation, I have to define ret
outside of the while
loop, and since sequential code is run before asynchronous code in the NodeJS event loop, I expect the logging will be executed before createPost()
, which is not what I want.
Question
Is it possible to only log ret
when createPost()
have been executed?
module.exports = async (p) => {
let ret = 0;
try {
while (true) {
switch (x) {
case 1:
isOk = await getStatusCode({ ... });
break
case 2:
isOk = await getString({ ... });
break
default:
throw "";
};
ret = await createPost(p);
appLogger.info(`Created post: ${ret}`); // I don't need 'ret' for anything else than logging it
} catch (error) {
appLogger.error(error);
}
}
createPost.js
const axios = require('axios');
module.exports = async (c) => {
try {
const r = await axios({ ... });
return r.data.key;
} catch (error) {
throw new Error(JSON.stringify(error.response.data, null, 2));
};
};
CodePudding user response:
...and since sequential code is run before asynchronous code in the NodeJS event loop, I expect the logging will be executed before createPost(), which is not what I want.
All of the code in an async
function after the first await
is asynchronous, not synchronous. In your code, the appLogger.info
call won't happen until createPost
has finished its work (asynchronously).
So there's no need to declare ret
outside the loop (and even if the above weren't true, that wouldn't really help), you can just do it inline, see ***
comments:
module.exports = async (p) => {
// *** No `ret` here
try {
while (true) {
switch (x) {
case 1:
isOk = await getStatusCode({ ... });
break
case 2:
isOk = await getString({ ... });
break
default:
throw "";
};
const ret = await createPost(p); // *** Declare it here
appLogger.info(`Created post: ${ret}`);
} catch (error) {
appLogger.error(error);
}
}
The code waits, asynchronously, at the await
and only continues when createPost
is done.
Here's a simplified example:
const randomDelay = () => new Promise(resolve => {
setTimeout(resolve, Math.floor(Math.random() * Math.floor(Math.random() * 300) 500));
});
async function doSomethingElse() {
await randomDelay();
}
async function createPost(i) {
await randomDelay();
return i * 2;
}
async function example(max) {
console.log("Starting (this log is synchronous)");
for (let i = 0; i < max; i) {
await doSomethingElse();
const ret = await createPost(i);
console.log(`i = ${i}, ret = ${ret}`);
}
console.log("All done");
}
console.log("Calling example");
example(5)
.then(() => {
console.log("example promise fulfilled");
})
.catch(error => {
console.error("example promise rejected", error);
});
console.log("Done calling example, it's running asynchronously");
<iframe name="sif1" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>
Technically, you don't need ret
at all, this would also work:
appLogger.info(`Created post: ${await createPost(p)}`);
but if it were me, I'd keep it as shown in the first code block above. It's easier to debug.