Reputation: 11
I am trying to get the result of an async function in my calculateOrderAmount function but it returns undefined. The console.log in the called function returns the good result, but inside calculateOrderAmount, I get undefined. Here is my code:
getMultiStrats = async () => {
await MultiStrats.findOne({}, (err, multiStrats) => {
if (err) {
return err
}
if(!multiStrats) {
return console.log('MultiStrat not found')
}
console.log('returns MultiStrat: ' + multiStrats)
return multiStrats
})
.catch(err => console.log(err))
}
async function calculateOrderAmount(balance, ticker){
const multiState = await StrategyController.getMultiStrats().catch((err) => console.log(err))
console.log('multiState: ' + multiState)
some logic
}
Here is the console log:
multiState: undefined
returns MultiStrat: {
_id: 5ff73c74d1135b39fc709b80,
positionsCount: 1,
inTradeCount: 0,
__v: 0
}
What did I miss? Thanks you very much for your time!
Upvotes: 0
Views: 130
Reputation: 21110
Assuming that you use mongoose. I suggest using the promise interface like described in the documentation.
const getMultiStrats = async () => {
const query = MultiStrats.findOne({});
let multiStrats;
try {
multiStrats = await query.exec();
} catch (error) {
return error;
}
if (multiStrats) {
console.log("returns MultiStrat: " + multiStrats);
} else {
console.log("MultiStrat not found");
}
return multiStrats;
}
I would personally not return the error, but instead just let the error be thrown. With the above code the caller of getMultiStrats
has to figure out if there return value is the expected result or an error. If you don't catch the error, it is thrown further up to the caller.
const getMultiStrats = async () => {
const multiStrats = await MultiStrats.findOne({}).exec();
if (multiStrats) {
console.log("returns MultiStrat: " + multiStrats);
} else {
console.log("MultiStrat not found");
}
return multiStrats;
}
You can further simplify this if you where to leave the console.log
of of the equation.
const getMultiStrats = () => MultiStrats.findOne({}).exec();
Upvotes: 0
Reputation: 56875
The current approach is pretty unclear--there's no need for .catch
, async
, await
all at once. return multiStrats
returns from the inside of the callback, not from getMultiStrats
. The async
/await
on getMultiStrats
is superfluous, just adding another promise wrapper that doesn't accomplish anything.
Given that findOne
as shown here uses a callback rather than a promise, you can either use callbacks all the way or you can promisify findOne
as follows, using .then
and .catch
in the caller:
const MultiStrats = {
findOne: (obj, cb) => cb(null, "I'm a multistrat!")
};
const StrategyController = {
getMultiStrats: () => new Promise((resolve, reject) =>
MultiStrats.findOne({}, (err, multiStrats) => {
if (err) {
return reject(err);
}
else if (multiStrats) {
return resolve(multiStrats);
}
reject(Error("Multistrat not found"));
})
)
};
const calculateOrderAmount = (balance, ticker) =>
StrategyController
.getMultiStrats()
.then(multiState => {
console.log('multiState: ' + multiState)
// some logic
})
.catch(err => console.error(err))
;
calculateOrderAmount();
Or use async
/await
and try
/catch
:
const MultiStrats = {
findOne: (obj, cb) => cb(null, "I'm a multistrat!")
};
const StrategyController = {
getMultiStrats: () => new Promise((resolve, reject) =>
MultiStrats.findOne({}, (err, multiStrats) => {
if (err) {
return reject(err);
}
else if (multiStrats) {
return resolve(multiStrats);
}
reject(Error("Multistrat not found"));
})
)
};
const calculateOrderAmount = async (balance, ticker) => {
try {
const multiState = await StrategyController.getMultiStrats();
console.log('multiState: ' + multiState)
// some logic
}
catch (err) {
console.error(err);
}
};
calculateOrderAmount();
If this is MongoDB's findOne
and already returns a promise, then you can just return the promise to the caller, optionally await
ing it and throwing for the null result:
const MultiStrats = {
findOne: async query => "I'm a multistrat!"
};
const StrategyController = {
getMultiStrats: async () => {
const result = await MultiStrats.findOne({});
if (result) {
return result;
}
throw Error("Multistrat not found");
}
};
const calculateOrderAmount = (balance, ticker) =>
StrategyController
.getMultiStrats()
.then(multiState => {
console.log('multiState: ' + multiState);
// some logic
})
.catch(err => console.error(err))
;
calculateOrderAmount();
Upvotes: 1
Reputation: 3405
You cannot return values from an inner callback and reach the outer function, I would suggest
1- only use promises
2- wrap your code with promise to be sure that await
will return the async
result the way you expect to have.
getMultiStrats = async () => {
return new Promise((resolve, reject) => {
MultiStrats.findOne({}, (err, multiStrats) => {
if (err) {
return err
}
if (!multiStrats) {
console.log('MultiStrat not found')
reject('MultiStrat not found')
}
console.log('returns MultiStrat: ' + multiStrats)
resolve(multiStrats);
})
.catch(err => {
console.log(err);
reject(err)
})
})
}
async function calculateOrderAmount(balance, ticker) {
try {
const multiState = await StrategyController.getMultiStrats()
console.log('multiState: ' + multiState)
// some logic
} catch (error) {
console.error(error);
}
}
Upvotes: 0