Почему res. json возвращается пустым? - PullRequest
0 голосов
/ 04 февраля 2020

Когда я выполняю запрос «GET» от клиента к серверу, сервер должен сделать axios.get() вызов API-интерфейса для получения данных для массива тикеров. Когда я вижу console.log, результаты, кажется, работают нормально, но массив, похоже, не сохраняется, как будто он стирается и возвращается к клиенту как пустой. Я думаю, что я могу испортить это с 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)
    })
})

1 Ответ

0 голосов
/ 04 февраля 2020

Вы звоните res.json(array) до того, как завершится любой из ваших вызовов currentPrice().then(...), поэтому массив все еще пуст.

Существует несколько различных способов решения этой проблемы. Вероятно, самое простое - изменить .forEach() l oop на обычный for l oop, а затем использовать 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(), чтобы просто вернуть топор ios Обещание напрямую
  2. Соответствующее отклонение в currentPrice(), если есть ошибка, чтобы вызывающая сторона увидела ошибку .
  3. Добавьте правильную обработку ошибок (отправив ответ об ошибке), если запрос БД не выполнен.
  4. Переключите .forEach() l oop на for l oop, чтобы мы могли используйте await для сериализации вызовов на currentPrice(), чтобы мы могли легче узнать, когда они все будут выполнены.
  5. Добавить обработку ошибок и отправку ответа об ошибке, если currentPrice() имеет ошибку.
  6. Вызов res.json(array) только после завершения всех теперь сериализованных вызовов await currentPrice().

К вашему сведению, полностью завершенное преобразование здесь переключится на mysql2, так что вы можете использовать интерфейс обещания для connection.query(), а не простой интерфейс обратного вызова, который вы используете сейчас. Это позволит вам упростить обработку ошибок в одном месте.

...