node.js middleware making code synchronous - node.js

I am trying to make res.locals.info available on every single page.
I'm trying to do this by middleware but I'm getting an error.
Apparently res.locals.info is not ready yet when the page render, thus I get an error info is not defined. How do I solve this?
app.use(function(req,res,next){
async function getInfo(user) {
let result = await info.search(user);
setInfo(result);
}
function setInfo(result){
res.locals.info= result;
}
getInfo(req.user);
return next();
})
search():
module.exports.search= function (user) {
var query=`SELECT count(*) as Info from dbo.InfoUsers WHERE user= '${user}' ;`
return new Promise((resolve, reject) => {
sequelize
.query(`${query}`, {model: InformationUser})
.then((info) => {
resolve(info);
})
})
};

You were calling next() before your getInfo() function had done its work, thus res.locals.info had not yet been set when you were trying to use it.
An async function returns a promise. It does NOT block until the await is done. Instead, it returns a promise immediately. You will need to use await or .then() on getInfo() so you know when it's actually done.
If info.search() returns a promise that resolves to the desired result, then you could do this:
app.use(function(req,res,next){
// this returns a promise that resolves when it's actually done
async function getInfo(user) {
let result = await info.search(user);
setInfo(result);
}
function setInfo(result){
res.locals.info= result;
}
// use .then() to know when getInfo() is done
// use .catch() to handle errors from getInfo()
getInfo(req.user).then(result => next()).catch(next);
});
And, you can remove the deferred anti-pattern from your search function and fix the error handling (which is a common issue when you use the anti-pattern). There is no need to wrap an existing promise in another promise.:
module.exports.search = function (user) {
var query=`SELECT count(*) as Info from dbo.InfoUsers WHERE user= '${user}' ;`
// return promise directly so caller can use .then() or await on it
return sequelize.query(`${query}`, {model: InformationUser});
};

Related

NodeJs async SyntaxError [duplicate]

I wrote this code in lib/helper.js:
var myfunction = async function(x,y) {
....
return [variableA, variableB]
}
exports.myfunction = myfunction;
Then I tried to use it in another file :
var helper = require('./helper.js');
var start = function(a,b){
....
const result = await helper.myfunction('test','test');
}
exports.start = start;
I got an error:
await is only valid in async function
What is the issue?
The error is not refering to myfunction but to start.
async function start() {
....
const result = await helper.myfunction('test', 'test');
}
// My function
const myfunction = async function(x, y) {
return [
x,
y,
];
}
// Start function
const start = async function(a, b) {
const result = await myfunction('test', 'test');
console.log(result);
}
// Call start
start();
I use the opportunity of this question to advise you about an known anti pattern using await which is : return await.
WRONG
async function myfunction() {
console.log('Inside of myfunction');
}
// Here we wait for the myfunction to finish
// and then returns a promise that'll be waited for aswell
// It's useless to wait the myfunction to finish before to return
// we can simply returns a promise that will be resolved later
// useless async here
async function start() {
// useless await here
return await myfunction();
}
// Call start
(async() => {
console.log('before start');
await start();
console.log('after start');
})();
CORRECT
async function myfunction() {
console.log('Inside of myfunction');
}
// Here we wait for the myfunction to finish
// and then returns a promise that'll be waited for aswell
// It's useless to wait the myfunction to finish before to return
// we can simply returns a promise that will be resolved later
// Also point that we don't use async keyword on the function because
// we can simply returns the promise returned by myfunction
function start() {
return myfunction();
}
// Call start
(async() => {
console.log('before start');
await start();
console.log('after start');
})();
Also, know that there is a special case where return await is correct and important : (using try/catch)
Are there performance concerns with `return await`?
To use await, its executing context needs to be async in nature
As it said, you need to define the nature of your executing context where you are willing to await a task before anything.
Just put async before the fn declaration in which your async task will execute.
var start = async function(a, b) {
// Your async task will execute with await
await foo()
console.log('I will execute after foo get either resolved/rejected')
}
Explanation:
In your question, you are importing a method which is asynchronous in nature and will execute in parallel. But where you are trying to execute that async method is inside a different execution context which you need to define async to use await.
var helper = require('./helper.js');
var start = async function(a,b){
....
const result = await helper.myfunction('test','test');
}
exports.start = start;
Wondering what's going under the hood
await consumes promise/future / task-returning methods/functions and async marks a method/function as capable of using await.
Also if you are familiar with promises, await is actually doing the same process of promise/resolve. Creating a chain of promise and executes your next task in resolve callback.
For more info you can refer to MDN DOCS.
When I got this error, it turned out I had a call to the map function inside my "async" function, so this error message was actually referring to the map function not being marked as "async". I got around this issue by taking the "await" call out of the map function and coming up with some other way of getting the expected behavior.
var myfunction = async function(x,y) {
....
someArray.map(someVariable => { // <- This was the function giving the error
return await someFunction(someVariable);
});
}
I had the same problem and the following block of code was giving the same error message:
repositories.forEach( repo => {
const commits = await getCommits(repo);
displayCommit(commits);
});
The problem is that the method getCommits() was async but I was passing it the argument repo which was also produced by a Promise. So, I had to add the word async to it like this: async(repo) and it started working:
repositories.forEach( async(repo) => {
const commits = await getCommits(repo);
displayCommit(commits);
});
If you are writing a Chrome Extension and you get this error for your code at root, you can fix it using the following "workaround":
async function run() {
// Your async code here
const beers = await fetch("https://api.punkapi.com/v2/beers");
}
run();
Basically you have to wrap your async code in an async function and then call the function without awaiting it.
The current implementation of async / await only supports the await keyword inside of async functions Change your start function signature so you can use await inside start.
var start = async function(a, b) {
}
For those interested, the proposal for top-level await is currently in Stage 2: https://github.com/tc39/proposal-top-level-await
async/await is the mechanism of handling promise, two ways we can do it
functionWhichReturnsPromise()
.then(result => {
console.log(result);
})
.cathc(err => {
console.log(result);
});
or we can use await to wait for the promise to full-filed it first, which means either it is rejected or resolved.
Now if we want to use await (waiting for a promise to fulfil) inside a function, it's mandatory that the container function must be an async function because we are waiting for a promise to fulfiled asynchronously || make sense right?.
async function getRecipesAw(){
const IDs = await getIds; // returns promise
const recipe = await getRecipe(IDs[2]); // returns promise
return recipe; // returning a promise
}
getRecipesAw().then(result=>{
console.log(result);
}).catch(error=>{
console.log(error);
});
If you have called async function inside foreach update it to for loop
Found the code below in this nice article: HTTP requests in Node using Axios
const axios = require('axios')
const getBreeds = async () => {
try {
return await axios.get('https://dog.ceo/api/breeds/list/all')
} catch (error) {
console.error(error)
}
}
const countBreeds = async () => {
const breeds = await getBreeds()
if (breeds.data.message) {
console.log(`Got ${Object.entries(breeds.data.message).length} breeds`)
}
}
countBreeds()
Or using Promise:
const axios = require('axios')
const getBreeds = () => {
try {
return axios.get('https://dog.ceo/api/breeds/list/all')
} catch (error) {
console.error(error)
}
}
const countBreeds = async () => {
const breeds = getBreeds()
.then(response => {
if (response.data.message) {
console.log(
`Got ${Object.entries(response.data.message).length} breeds`
)
}
})
.catch(error => {
console.log(error)
})
}
countBreeds()
In later nodejs (>=14), top await is allowed with { "type": "module" } specified in package.json or with file extension .mjs.
https://www.stefanjudis.com/today-i-learned/top-level-await-is-available-in-node-js-modules/
This in one file works..
Looks like await only is applied to the local function which has to be async..
I also am struggling now with a more complex structure and in between different files. That's why I made this small test code.
edit: i forgot to say that I'm working with node.js.. sry. I don't have a clear question. Just thought it could be helpful with the discussion..
function helper(callback){
function doA(){
var array = ["a ","b ","c "];
var alphabet = "";
return new Promise(function (resolve, reject) {
array.forEach(function(key,index){
alphabet += key;
if (index == array.length - 1){
resolve(alphabet);
};
});
});
};
function doB(){
var a = "well done!";
return a;
};
async function make() {
var alphabet = await doA();
var appreciate = doB();
callback(alphabet+appreciate);
};
make();
};
helper(function(message){
console.log(message);
});
A common problem in Express:
The warning can refer to the function, or where you call it.
Express items tend to look like this:
app.post('/foo', ensureLoggedIn("/join"), (req, res) => {
const facts = await db.lookup(something)
res.redirect('/')
})
Notice the => arrow function syntax for the function.
The problem is NOT actually in the db.lookup call, but right here in the Express item.
Needs to be:
app.post('/foo', ensureLoggedIn("/join"), async function (req, res) {
const facts = await db.lookup(something)
res.redirect('/')
})
Basically, nix the => and add async function .
"await is only valid in async function"
But why? 'await' explicitly turns an async call into a synchronous call, and therefore the caller cannot be async (or asyncable) - at least, not because of the call being made at 'await'.
Yes, await / async was a great concept, but the implementation is completely broken.
For whatever reason, the await keyword has been implemented such that it can only be used within an async method. This is in fact a bug, though you will not see it referred to as such anywhere but right here. The fix for this bug would be to implement the await keyword such that it can only be used TO CALL an async function, regardless of whether the calling function is itself synchronous or asynchronous.
Due to this bug, if you use await to call a real asynchronous function somewhere in your code, then ALL of your functions must be marked as async and ALL of your function calls must use await.
This essentially means that you must add the overhead of promises to all of the functions in your entire application, most of which are not and never will be asynchronous.
If you actually think about it, using await in a function should require the function containing the await keyword TO NOT BE ASYNC - this is because the await keyword is going to pause processing in the function where the await keyword is found. If processing in that function is paused, then it is definitely NOT asynchronous.
So, to the developers of javascript and ECMAScript - please fix the await/async implementation as follows...
await can only be used to CALL async functions.
await can appear in any kind of function, synchronous or asynchronous.
Change the error message from "await is only valid in async function" to "await can only be used to call async functions".

How can I use a variable outside of the .then() scope

I have the following situation:
Why does the clients variable resolve in undefined when I call it below;
function getClientList() {
TeamSpeak.connect({
host: "localhost",
serverport: 9987,
nickname: "NodeJS Query Framework",
}).then(async (teamspeak) => {
const clients = await teamspeak.clientList({ clientType: 0 });
if (clients) return clients;
else return null;
});
}
When I call it like that it resolves as undefined
const clients = getClientList();
The short answer to your question is that you cannot use a resulting variable until the Promise resolves. Whether you use .then or await it's really the same mechanism and you can't access the result of your call until it's ready.
You can only get the results of it by waiting for the Promise to resolve. This can be done by using await if your function is marked as async, or by using the .then() function on the Promise since it will get called after the result is ready.
Think of the Promise as a black box that has a then function in it. Remember that each .then() function also returns as a Promise object which is why you can chain them as promise.then(...).then(...).then(...);. Your code then looks like this:
function getClientList() {
PROMISE1.then(someFunction);
}
const clients = getClientList();
Note that even though it spans multiple lines, your getClientList function is really just one line of code TeamSpeak.connect(...).then(...);
There are a few things wrong with your code. Let's go through them one by one:
The getClientList function doesn't return anything explicitly. In its most basic form it's function getClientList() { someCall(); } and that returns undefined by default. That's why clients is always undefined.
If you add a return statement to the function, it will return a Promise and might look like this:
function getClientList() {
return PROMISE1.then(someFunction);
}
const clients = getClientList();
This is better because clients is not undefined any more, but it will be the Promise that may not have finished its work yet. To see the result of the call you'd need to use the then function like clients.then(result => console.log(result)) to allow it to wait for the asynchronous work to complete.
You're using both .then and async/await. It will probably be cleaner and easier to work with if you go with one or the other (await is my preference). Your code can look like this:
async function getClientList() {
const teamspeak = await TeamSpeak.connect({
host: "localhost",
serverport: 9987,
nickname: "NodeJS Query Framework",
});
const clients = await teamspeak.clientList({ clientType: 0 });
return clients || null; // returns as a Promise resolving to clients or null
}
const clients = await getClientList(); // assuming you're in another async fn
There is no error handling. If any of the asynchronous calls fail then the Promise will either reject or cause an exception. You should handle that by either surrounding it with a try/catch block at some level, or by adding .catch() after the final then, or by adding a second function to the .then() call to handle a rejection.
So putting it all together your code could look like this:
async function getClientList() {
const teamspeak = await TeamSpeak.connect({
host: "localhost",
serverport: 9987,
nickname: "NodeJS Query Framework",
});
return await teamspeak.clientList({ clientType: 0 }) || null;
}
// Example calling getClientList using ".then"
getClientList()
.then(
client => {
/* use the client value in this scope */
},
reason => {/* report the reason for rejection */}
) // end of .then
.catch(err => {/* report the error */});
// Example calling getClientList using "await"
try {
const client = await getClientList();
/* use the client value in this scope */
} catch (err) {/* report the error */}
No matter how you make the call, you're only able to access the clients value (returned by calling the clientList function) within the scope of either the .then or after await.
When you call getClientList() the inner "connect" function is started instantly in your library while the "then" callback is left to be executed in a future you can't know (when your library has completed the task triggered in "connect").
Preparing this "then" callback is done instantly, so getClientList() ends without returning anything.
The "return" instructions inside "then" are not returns for getClientList() but for the one who executes the callback (the code in your library).
What you can do is promissify the process: Return a promise that can be waited for and will be solved in the future when callback has been executed.
Try it like this:
function getClientList() {
// Tell the function caller that he will have the result at some time in the future.
// In other words: return a promise.
return new Promise( (resolve,reject) => {
TeamSpeak.connect({
host: "localhost",
serverport: 9987,
nickname: "NodeJS Query Framework",
}).then(async (teamspeak) => {
const clients = await teamspeak.clientList({ clientType: 0 });
// Give the caller that is waiting by holding the promise the desired result.
if (clients) resolve(clients);
// Throw error to the caller that is waiting by holding the promise .
else reject('Connect failed');
});
});
}
But notice you must await for the promise inside an "async" function. Otherwise you would block the main thread.
async function main() {
const clients = await getClientList();
}
Do set a try/catch as the promise might throw an error if "reject" is executed:
async function main() {
try{
const clients = await getClientList();
} catch(err){
console.log(err);
// Will show:
// Connect failed
}
}

NodeJS Await Within Await Unexpected Token [duplicate]

I wrote this code in lib/helper.js:
var myfunction = async function(x,y) {
....
return [variableA, variableB]
}
exports.myfunction = myfunction;
Then I tried to use it in another file :
var helper = require('./helper.js');
var start = function(a,b){
....
const result = await helper.myfunction('test','test');
}
exports.start = start;
I got an error:
await is only valid in async function
What is the issue?
The error is not refering to myfunction but to start.
async function start() {
....
const result = await helper.myfunction('test', 'test');
}
// My function
const myfunction = async function(x, y) {
return [
x,
y,
];
}
// Start function
const start = async function(a, b) {
const result = await myfunction('test', 'test');
console.log(result);
}
// Call start
start();
I use the opportunity of this question to advise you about an known anti pattern using await which is : return await.
WRONG
async function myfunction() {
console.log('Inside of myfunction');
}
// Here we wait for the myfunction to finish
// and then returns a promise that'll be waited for aswell
// It's useless to wait the myfunction to finish before to return
// we can simply returns a promise that will be resolved later
// useless async here
async function start() {
// useless await here
return await myfunction();
}
// Call start
(async() => {
console.log('before start');
await start();
console.log('after start');
})();
CORRECT
async function myfunction() {
console.log('Inside of myfunction');
}
// Here we wait for the myfunction to finish
// and then returns a promise that'll be waited for aswell
// It's useless to wait the myfunction to finish before to return
// we can simply returns a promise that will be resolved later
// Also point that we don't use async keyword on the function because
// we can simply returns the promise returned by myfunction
function start() {
return myfunction();
}
// Call start
(async() => {
console.log('before start');
await start();
console.log('after start');
})();
Also, know that there is a special case where return await is correct and important : (using try/catch)
Are there performance concerns with `return await`?
To use await, its executing context needs to be async in nature
As it said, you need to define the nature of your executing context where you are willing to await a task before anything.
Just put async before the fn declaration in which your async task will execute.
var start = async function(a, b) {
// Your async task will execute with await
await foo()
console.log('I will execute after foo get either resolved/rejected')
}
Explanation:
In your question, you are importing a method which is asynchronous in nature and will execute in parallel. But where you are trying to execute that async method is inside a different execution context which you need to define async to use await.
var helper = require('./helper.js');
var start = async function(a,b){
....
const result = await helper.myfunction('test','test');
}
exports.start = start;
Wondering what's going under the hood
await consumes promise/future / task-returning methods/functions and async marks a method/function as capable of using await.
Also if you are familiar with promises, await is actually doing the same process of promise/resolve. Creating a chain of promise and executes your next task in resolve callback.
For more info you can refer to MDN DOCS.
When I got this error, it turned out I had a call to the map function inside my "async" function, so this error message was actually referring to the map function not being marked as "async". I got around this issue by taking the "await" call out of the map function and coming up with some other way of getting the expected behavior.
var myfunction = async function(x,y) {
....
someArray.map(someVariable => { // <- This was the function giving the error
return await someFunction(someVariable);
});
}
I had the same problem and the following block of code was giving the same error message:
repositories.forEach( repo => {
const commits = await getCommits(repo);
displayCommit(commits);
});
The problem is that the method getCommits() was async but I was passing it the argument repo which was also produced by a Promise. So, I had to add the word async to it like this: async(repo) and it started working:
repositories.forEach( async(repo) => {
const commits = await getCommits(repo);
displayCommit(commits);
});
If you are writing a Chrome Extension and you get this error for your code at root, you can fix it using the following "workaround":
async function run() {
// Your async code here
const beers = await fetch("https://api.punkapi.com/v2/beers");
}
run();
Basically you have to wrap your async code in an async function and then call the function without awaiting it.
The current implementation of async / await only supports the await keyword inside of async functions Change your start function signature so you can use await inside start.
var start = async function(a, b) {
}
For those interested, the proposal for top-level await is currently in Stage 2: https://github.com/tc39/proposal-top-level-await
async/await is the mechanism of handling promise, two ways we can do it
functionWhichReturnsPromise()
.then(result => {
console.log(result);
})
.cathc(err => {
console.log(result);
});
or we can use await to wait for the promise to full-filed it first, which means either it is rejected or resolved.
Now if we want to use await (waiting for a promise to fulfil) inside a function, it's mandatory that the container function must be an async function because we are waiting for a promise to fulfiled asynchronously || make sense right?.
async function getRecipesAw(){
const IDs = await getIds; // returns promise
const recipe = await getRecipe(IDs[2]); // returns promise
return recipe; // returning a promise
}
getRecipesAw().then(result=>{
console.log(result);
}).catch(error=>{
console.log(error);
});
If you have called async function inside foreach update it to for loop
Found the code below in this nice article: HTTP requests in Node using Axios
const axios = require('axios')
const getBreeds = async () => {
try {
return await axios.get('https://dog.ceo/api/breeds/list/all')
} catch (error) {
console.error(error)
}
}
const countBreeds = async () => {
const breeds = await getBreeds()
if (breeds.data.message) {
console.log(`Got ${Object.entries(breeds.data.message).length} breeds`)
}
}
countBreeds()
Or using Promise:
const axios = require('axios')
const getBreeds = () => {
try {
return axios.get('https://dog.ceo/api/breeds/list/all')
} catch (error) {
console.error(error)
}
}
const countBreeds = async () => {
const breeds = getBreeds()
.then(response => {
if (response.data.message) {
console.log(
`Got ${Object.entries(response.data.message).length} breeds`
)
}
})
.catch(error => {
console.log(error)
})
}
countBreeds()
In later nodejs (>=14), top await is allowed with { "type": "module" } specified in package.json or with file extension .mjs.
https://www.stefanjudis.com/today-i-learned/top-level-await-is-available-in-node-js-modules/
This in one file works..
Looks like await only is applied to the local function which has to be async..
I also am struggling now with a more complex structure and in between different files. That's why I made this small test code.
edit: i forgot to say that I'm working with node.js.. sry. I don't have a clear question. Just thought it could be helpful with the discussion..
function helper(callback){
function doA(){
var array = ["a ","b ","c "];
var alphabet = "";
return new Promise(function (resolve, reject) {
array.forEach(function(key,index){
alphabet += key;
if (index == array.length - 1){
resolve(alphabet);
};
});
});
};
function doB(){
var a = "well done!";
return a;
};
async function make() {
var alphabet = await doA();
var appreciate = doB();
callback(alphabet+appreciate);
};
make();
};
helper(function(message){
console.log(message);
});
A common problem in Express:
The warning can refer to the function, or where you call it.
Express items tend to look like this:
app.post('/foo', ensureLoggedIn("/join"), (req, res) => {
const facts = await db.lookup(something)
res.redirect('/')
})
Notice the => arrow function syntax for the function.
The problem is NOT actually in the db.lookup call, but right here in the Express item.
Needs to be:
app.post('/foo', ensureLoggedIn("/join"), async function (req, res) {
const facts = await db.lookup(something)
res.redirect('/')
})
Basically, nix the => and add async function .
"await is only valid in async function"
But why? 'await' explicitly turns an async call into a synchronous call, and therefore the caller cannot be async (or asyncable) - at least, not because of the call being made at 'await'.
Yes, await / async was a great concept, but the implementation is completely broken.
For whatever reason, the await keyword has been implemented such that it can only be used within an async method. This is in fact a bug, though you will not see it referred to as such anywhere but right here. The fix for this bug would be to implement the await keyword such that it can only be used TO CALL an async function, regardless of whether the calling function is itself synchronous or asynchronous.
Due to this bug, if you use await to call a real asynchronous function somewhere in your code, then ALL of your functions must be marked as async and ALL of your function calls must use await.
This essentially means that you must add the overhead of promises to all of the functions in your entire application, most of which are not and never will be asynchronous.
If you actually think about it, using await in a function should require the function containing the await keyword TO NOT BE ASYNC - this is because the await keyword is going to pause processing in the function where the await keyword is found. If processing in that function is paused, then it is definitely NOT asynchronous.
So, to the developers of javascript and ECMAScript - please fix the await/async implementation as follows...
await can only be used to CALL async functions.
await can appear in any kind of function, synchronous or asynchronous.
Change the error message from "await is only valid in async function" to "await can only be used to call async functions".

object Promise on return

Whenever I'm trying to generate random keys from crypto or nanoid (new library) it just returns [object Promise]
async function createCode(length){
if(!length){
return nanoid;
} else {
return nanoid(length);
}
}
// another one for example
async function createCode(){
return await crypto.randomBytes(64).toString('hex');
}
An async function returns a promise by default. Please call await createCode() in another async function or use createCode().then()
All async function return a promise. Always.
So, the caller of an async function has to either use await themselves (from within another async function) or use .then() to get the value out of the promise.
It doesn't look to me like either of your functions benefit from being async. return await someFunc() when someFunc() returns a promise can be done with just return someFunc() just the same. The await is not necessary at all.
FYI, crypto.randomBytes() uses a callback if you want the asynchronous version. If you don't pass it a callback, then it's just a plain synchronous function. Unless you've done something to make a promisified version of that library, it doesn't return a promise.
So, you can just use this:
// another one for example
function createCode(){
return crypto.randomBytes(64).toString('hex');
}
Which you can just call as a regular function:
let randomVal = createCode();
console.log(randomVal);
If you want the asynchronous version and want to use it with promises, then you'd have to promisify it:
// another one for example
function createCode(){
return new Promise((resolve, reject) => {
crypto.randomBytes(64, function(err, val) {
if (err) return reject(err);
resolve(val.toString('hex'));
});
});
}
Then, you can call it:
createCode().then(val => {
console.log(val);
}).catch(err => {
console.log(err);
});

Node.js MongoDb find function ignores wait

I need the callback function of find from Node.js mongodb 3.1.6 to be triggered before the return statement of an async function, however the return statement is called before the callback function even-though there is a wait in front.
async function(myId) {
const myObject = MyObject()
await collection.find({where: {id: myId}}, async (err, results) => {
if (err) {
logger.error('error');
}
myObject.add(results);
});
return myObject
}
I have seen some examples where instead of find(query, callback) the pattern find(query).toArray() was used. But this doesn't run at all in my case. We use Node.js mongodb 3.1.6 with loopback-connector-mongodb maybe this is related to the problem.
If mongo doesn't provide a promise-answering function, then promisify this one yourself. Neither that promise-creating wrapper nor the anonymous callback it uses should be declared async, but the caller should....
function findById(collection, myId) {
return new Promise((resolve, reject) => {
collection.find({where: {id: myId}}, (err, results) => {
(err)? reject(err): resolve(results);
});
});
}
// now callers can use the async await pattern...
async someFunction() {
try {
let myId = // ...
let collection = // ...
let results = await findById(collection, myId);
// do something with results
} catch (err) {
// error
}
}
The key idea is that collection.find with the callback isn't eligible for await, because it doesn't return a promise. The anonymous callback function you pass to it isn't an async function... it does its work right away, as soon as find calls it back. So we build a promise around mongo, then use the new async/await syntax with that promise.

Resources