【问题标题】:Why is res.json returning empty?为什么 res.json 返回空?
【发布时间】:2020-02-05 09:50:15
【问题描述】:

当我从客户端向服务器发出“GET”请求时,服务器应该向股票 API 发出 axios.get() 调用,以检索一系列代码的数据。当我控制台记录结果时,它似乎工作正常,但数组似乎没有保存,就像它被清除并以空的形式返回客户端一样。我想我可能会用async/await 搞砸这件事。

async function currentPrice(ticker) {
    const apiURL = `https://www.alphavantage.co/query?function=GLOBAL_QUOTE&symbol=${ticker}&apikey=${API_KEY}`;
    let price;

    await axios.get(apiURL).then(data => {
        try { 
            price = data.data["Global Quote"]["05. price"];
        } catch (error) {
            console.log(error)
        }
    })
    return price;
};

app.get("/refresh", redirectLogin, (req, res) => {
    const {
        user
    } = res.locals;
    var array = [];
    connection.query(`SELECT * FROM holdings WHERE user_name = '${user.user_name}' AND quantity > 0`, (err, results) => {
        if (err) throw err;
        results.forEach(holding => {
            currentPrice(holding.ticker).then(data => {
                var updatedTicker = {
                    ticker: holding.ticker,
                    description: holding.description,
                    price_acquired: holding.price_acquired,
                    market_price: data,
                    delta: parseFloat(this.market_price) - parseFloat(this.price_acquired),
                    quantity: holding.quantity,
                    trade_date: holding.date_acquired
                }
                array.push(updatedTicker);
                // console.log(array);
                console.log(updatedTicker.market_price)
            })
        })
        res.json(array)
    })
})

【问题讨论】:

  • 在您的任何currentPrice().then() 完成之前,您正在调用res.json()

标签: arrays rest promise


【解决方案1】:

您在任何currentPrice().then(...) 调用完成之前调用res.json(array),因此数组仍然是空的。

有许多不同的方法可以解决这个问题。可能最简单的是将.forEach() 循环更改为普通的for 循环,然后使用async/await 序列化您对currentPrice() 的每个调用:

function currentPrice(ticker) {
    const apiURL = `https://www.alphavantage.co/query?function=GLOBAL_QUOTE&symbol=${ticker}&apikey=${API_KEY}`;

    return axios.get(apiURL).then(data => {
        try {
            return data.data["Global Quote"]["05. price"];
        }
        catch (error) {
            console.log(error);
            throw error;
        }
    });
}


app.get("/refresh", redirectLogin,  (req, res) => {

    const { user } = res.locals;
    connection.query(`SELECT * FROM holdings WHERE user_name = '${user.user_name}' AND quantity > 0`,  async (err, results) => {
        if (err) {
            console.log(err);
            res.sendStatus(500);
            return;
        }

        try {
            const array = [];
            for (let holding of results) {
                let data = await currentPrice(holding.ticker);
                let updatedTicker = {
                    ticker: holding.ticker,
                    description: holding.description,
                    price_acquired: holding.price_acquired,
                    market_price: data,
                    delta: parseFloat(this.market_price) - parseFloat(this.price_acquired),
                    quantity: holding.quantity,
                    trade_date: holding.date_acquired

                }
                array.push(updatedTicker);
            }
            res.json(array);
        } catch(e) {
            console.log(e);
            res.sendStatus(500);
        }
    });
});

各种变化:

  1. currentPrice() 函数简化为直接返回axios promise
  2. 如果出现错误,请在currentPrice() 中适当地拒绝,以便调用者看到错误。
  3. 如果数据库查询失败,添加适当的错误处理(发送错误响应)。
  4. .forEach() 循环切换到for 循环,这样我们就可以使用await 序列化对currentPrice() 的调用,这样我们就可以更轻松地知道它们什么时候都完成了。
  5. 如果currentPrice() 出现错误,则添加错误处理和发送错误响应。
  6. 只有在对 await currentPrice() 的所有现在序列化调用都完成后,才能调用 res.json(array)

仅供参考,此处完全完整的转换将切换到 mysql2,因此您可以使用 connection.query() 的 promise 接口,而不是您现在使用的普通回调接口。这样您就可以更轻松地将错误处理整合到一个地方。

【讨论】:

  • 哇,这太棒了!非常感谢您的智慧,编辑工作正常!
猜你喜欢
  • 1970-01-01
  • 2017-01-17
  • 2015-10-23
  • 1970-01-01
  • 2023-01-08
  • 2021-01-26
  • 2018-02-01
  • 2014-02-24
  • 1970-01-01
相关资源
最近更新 更多