Vincent
Vincent

Reputation: 11

async function not getting result

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

Answers (3)

3limin4t0r
3limin4t0r

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

ggorlen
ggorlen

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 awaiting 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

Louay Al-osh
Louay Al-osh

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

Related Questions