最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Using asyncawait still returns undefined - Stack Overflow

programmeradmin0浏览0评论

I asked recently about the asynchronous in javascript, request-promise module returns undefined. I quite understand it after someone gave the same SO question which is the How do I return the response from an asynchronous call?. I learned a lot which helps me to how properly request an api. But now I encounter the same problem even though I'm using async/await already. I put comments where I'm getting an undefined.

const request = require('request');
const rp = require('request-promise');

const MongoClient = require('mongodb').MongoClient;
const ObjectId = require('mongodb').ObjectID;

const CONNECTION_STRING = process.env.DB;
const dbName = 'fcc';
const connectionOption = { useNewUrlParser: true };

function StockHandler() {

  this.latestWithoutLike = async function(ticker, multipleStock, callback) {
    if (!multipleStock) {
      console.log('Single stock');
      let lastPrice = await getLastPrice(ticker);

      if (typeof lastPrice === 'string') {
        getLikes(ticker, false, (data) => {

          let stockData = {
            stock: data.stock,
            price: lastPrice,
            likes: data.likes
          }

          return callback({ stockData: stockData });
        });
      }
    } else {
      console.log('Multiple stock');
      let firstStockLastPrice = await getLastPrice(ticker[0]);
      let secondStockLastPrice = await getLastPrice(ticker[1]);

      if (typeof firstStockLastPrice === 'string' && typeof secondStockLastPrice === 'string') {
        let firstStockLikes = await getLikes(ticker[0], false, (data) => { return data; });
        let secondStockLikes = await getLikes(ticker[1], false, (data) => { return data; });

        console.log(firstStockLikes); // <--- undefined
        console.log(secondStockLikes); // <--- undefined
      }

    } 
  };

  this.latestWithLike = async function(ticker, multipleStock, callback) {
    if (!multipleStock) {
      console.log('Single stock');
      let lastPrice = await getLastPrice(ticker);
      console.log(lastPrice);
      if (typeof lastPrice === 'string') {
        getLikes(ticker, true, (data) => {

          let stockData = {
            stock: data.stock,
            price: lastPrice,
            likes: data.likes + 1
          }

          return callback({ stockData: stockData });
        });
      }

    } else {
      console.log('Multiple stock');
      let firstStockLastPrice = await getLastPrice(ticker[0]);
      let secondStockLastPrice = await getLastPrice(ticker[1]);
      console.log(firstStockLastPrice);
      console.log(secondStockLastPrice);
    }
  };  

}

function getLastPrice(ticker) {
  let options = {
    uri:  `;symbol=${ticker}&interval=1min&apikey=${process.env.ALPHA_KEY}`,
    method: 'GET',
    json: true
  }

  return rp(options)
    .then(function(parsedBody){
      let latestStockTradeTime = Object.keys(parsedBody[Object.keys(parsedBody)[1]])[0];
      let closingPrice = parsedBody[Object.keys(parsedBody)[1]][latestStockTradeTime]['4. close'];
      return closingPrice;
    })
    .catch(function(error){
      return error;
    })
}

function getLikes(ticker, likeStatus, callback) {
  MongoClient.connect(CONNECTION_STRING, connectionOption, (err, client) => {

    if (err) callback(err);

    const db = client.db(dbName);
    const collection = db.collection('stock');

    if (!likeStatus) {
      try {
        collection.findOne(
          { stock: ticker.toUpperCase() },
          { upsert: true },
          (err, result) => {
            if (result === null) {
              collection.insertOne(
                { stock: ticker.toUpperCase(), likes: 0 },
                { upsert: true },
                (err, result) => {
                  return callback(result.ops[0]);
                }
              ); 
            } else {
                return callback(result);
            }
          }
        );
      } catch (e) {
          return callback({ error: e });
      }  
    } 
    else {
      try {
        collection.findOneAndUpdate(
          { stock: ticker.toUpperCase() },
          { $inc : { likes: 1 } },
          { upsert: true, new: true },
          (err, data) => {
            return callback(data.value);
          }
        );
      } catch (e) {
          return callback({ error: e });
      }
    }

  });
};

module.exports = StockHandler;

I asked recently about the asynchronous in javascript, request-promise module returns undefined. I quite understand it after someone gave the same SO question which is the How do I return the response from an asynchronous call?. I learned a lot which helps me to how properly request an api. But now I encounter the same problem even though I'm using async/await already. I put comments where I'm getting an undefined.

const request = require('request');
const rp = require('request-promise');

const MongoClient = require('mongodb').MongoClient;
const ObjectId = require('mongodb').ObjectID;

const CONNECTION_STRING = process.env.DB;
const dbName = 'fcc';
const connectionOption = { useNewUrlParser: true };

function StockHandler() {

  this.latestWithoutLike = async function(ticker, multipleStock, callback) {
    if (!multipleStock) {
      console.log('Single stock');
      let lastPrice = await getLastPrice(ticker);

      if (typeof lastPrice === 'string') {
        getLikes(ticker, false, (data) => {

          let stockData = {
            stock: data.stock,
            price: lastPrice,
            likes: data.likes
          }

          return callback({ stockData: stockData });
        });
      }
    } else {
      console.log('Multiple stock');
      let firstStockLastPrice = await getLastPrice(ticker[0]);
      let secondStockLastPrice = await getLastPrice(ticker[1]);

      if (typeof firstStockLastPrice === 'string' && typeof secondStockLastPrice === 'string') {
        let firstStockLikes = await getLikes(ticker[0], false, (data) => { return data; });
        let secondStockLikes = await getLikes(ticker[1], false, (data) => { return data; });

        console.log(firstStockLikes); // <--- undefined
        console.log(secondStockLikes); // <--- undefined
      }

    } 
  };

  this.latestWithLike = async function(ticker, multipleStock, callback) {
    if (!multipleStock) {
      console.log('Single stock');
      let lastPrice = await getLastPrice(ticker);
      console.log(lastPrice);
      if (typeof lastPrice === 'string') {
        getLikes(ticker, true, (data) => {

          let stockData = {
            stock: data.stock,
            price: lastPrice,
            likes: data.likes + 1
          }

          return callback({ stockData: stockData });
        });
      }

    } else {
      console.log('Multiple stock');
      let firstStockLastPrice = await getLastPrice(ticker[0]);
      let secondStockLastPrice = await getLastPrice(ticker[1]);
      console.log(firstStockLastPrice);
      console.log(secondStockLastPrice);
    }
  };  

}

function getLastPrice(ticker) {
  let options = {
    uri:  `https://www.alphavantage.co/query?function=TIME_SERIES_INTRADAY&symbol=${ticker}&interval=1min&apikey=${process.env.ALPHA_KEY}`,
    method: 'GET',
    json: true
  }

  return rp(options)
    .then(function(parsedBody){
      let latestStockTradeTime = Object.keys(parsedBody[Object.keys(parsedBody)[1]])[0];
      let closingPrice = parsedBody[Object.keys(parsedBody)[1]][latestStockTradeTime]['4. close'];
      return closingPrice;
    })
    .catch(function(error){
      return error;
    })
}

function getLikes(ticker, likeStatus, callback) {
  MongoClient.connect(CONNECTION_STRING, connectionOption, (err, client) => {

    if (err) callback(err);

    const db = client.db(dbName);
    const collection = db.collection('stock');

    if (!likeStatus) {
      try {
        collection.findOne(
          { stock: ticker.toUpperCase() },
          { upsert: true },
          (err, result) => {
            if (result === null) {
              collection.insertOne(
                { stock: ticker.toUpperCase(), likes: 0 },
                { upsert: true },
                (err, result) => {
                  return callback(result.ops[0]);
                }
              ); 
            } else {
                return callback(result);
            }
          }
        );
      } catch (e) {
          return callback({ error: e });
      }  
    } 
    else {
      try {
        collection.findOneAndUpdate(
          { stock: ticker.toUpperCase() },
          { $inc : { likes: 1 } },
          { upsert: true, new: true },
          (err, data) => {
            return callback(data.value);
          }
        );
      } catch (e) {
          return callback({ error: e });
      }
    }

  });
};

module.exports = StockHandler;
Share Improve this question asked Nov 20, 2018 at 2:44 isemajisemaj 5871 gold badge6 silver badges21 bronze badges 4
  • 2 If you want to use async/await then getLikes() needs to return a promise. – Mark Commented Nov 20, 2018 at 2:46
  • What are the other options just in case I don't want to use async/await ? – isemaj Commented Nov 20, 2018 at 2:49
  • This is a lot of code to review. Basically, what @MarkMeyer said: just like a synchronous function, a function using async/await should return a value if you need to chain it, the difference being an async function() wraps its return value (or error) in a Promise. – stealththeninja Commented Nov 20, 2018 at 2:50
  • Does it mean that any function called inside the async function() needs to use await? Because I'm still confuse especially when I remove the await on that two I'm still getting undefined. – isemaj Commented Nov 20, 2018 at 2:56
Add a comment  | 

1 Answer 1

Reset to default 13

If you're defining a function with asynchronous behavior, you can use async/await or Promise chaining. Inside an async function, you can use await or chain .then() to wait for asynchronous responses. Your function returns a Promise with the resolved value or error to its callers.

async function getLikes() {
  const likes = await db.get('myLikes'); // this db method returns a Promise
  // ...
  return likes; // will return a Promise resolving likes from db or an error if there is one
}

async function logLikes() {
  const result = await getLikes();
  console.log(result);
}

If you're consuming an asynchronous function and do not await or chain the response like in this example...

async function getLikes() {
  const likes = db.get('myLikes'); // uh oh, this is asynchronous
  // ...
  return likes;
}

... the thread can move on before the return value is assigned to like. That may be where you're seeing undefined issues.

发布评论

评论列表(0)

  1. 暂无评论