从 Nodejs 中的 mySQL 获取数据时如何从 Async/await 函数获取返回值

Posted

技术标签:

【中文标题】从 Nodejs 中的 mySQL 获取数据时如何从 Async/await 函数获取返回值【英文标题】:How to get return values from Async/await function when fetching the data from mySQL in Nodejs 【发布时间】:2019-10-17 18:26:38 【问题描述】:

我正在从 DB 中获取一些交换数据,然后提取不同交换的名称并再次传递给 mysql 查询以从不同的表中获取数据。

我面临的问题是异步等待不返回值,而只是返回 Promise 。

下面是我正在尝试的代码,想知道我哪里出错了。

//Function that fetches the exchanges from DB

const getExchange = () => 
        return new Promise((resolve, reject) => 
            db.connection.query(`
            SELECT  *
            FROM,
            (
            SELECT
                exchange,
                COUNT(pair) as noOfMarkets
                FROM ticker_data

        ) as t
            `, (err, resp) => 
                if (!err) 
                    resolve(resp)
                 else 
                    reject(err)
                
            )
        )
    


// push unique exchanges to an array.
const getExchangesData = async () => 
    const allExchanges = await getExchanges();

    let exchanges = []
    allExchanges.forEach(item => 
        let exchange = 
            exchange: item.exchange
        
        exchanges.push(exchange)
    )
    return await exchanges



// mapping through an array of exchanges and passing to DB query to get data from the DB.

const getSingleExchange = async () => 
    const exchanges = await getExchangesData()
    await Promise.all(exchanges.map(async (item) => 
        db.connection.query(`
        SELECT
       exchange_rank,
       name
       volume24hUSD
       (
            SELECT
            volume24hUSD as tradingVolYesterday
            FROM exchanges
            WHERE name = '$item.exchange'
            AND createdAt >= now() -interval 1 day
            AND createdAt <  now() -interval 1 day + interval 120 second
            LIMIT 1
       ) volumeDay1
FROM exchanges
WHERE name = '$item.exchange'
        `, (err, resp) => 
            if (!err) 
                console.log(resp) // getting all the values

                let volData = 
                     name: resp[0].name,
                     exchange_rank: resp[0].exchange_rank,
                     icon: resp[0].icon
                 
                 return volData 
            
        )
    ))



const data = getSingleExchange()
console.log(data) // returning Promise  <pending>  

编辑

在回答中建议进行更改后,我仍然有一个问题:

//Function that fetches the exchanges from DB

const getExchange = () => 
        return new Promise((resolve, reject) => 
            db.connection.query(`
            SELECT  *
            FROM,
            (
            SELECT
                exchange,
                COUNT(pair) as noOfMarkets
                FROM ticker_data

        ) as t
            `, (err, resp) => 
                if (!err) 
                    resolve(resp)
                 else 
                    reject(err)
                
            )
        )
    


// push unique exchanges to an array.
const getExchangesData = async () => 
    const allExchanges = await getExchanges();

    let exchanges = []
    allExchanges.forEach(item => 
        let exchange = 
            exchange: item.exchange
        
        exchanges.push(exchange)
    )
    return await exchanges



    // mapping through an array of exchanges and passing to DB query to get data from the DB.

const getSingleExchange = async () => 
    const exchanges = await getExchangesData()
    await Promise.all(exchanges.map((item) => 
        return new Promise((resolve, reject) => 
            db.connection.query(`...`, (err, resp) => 
                if (!err) 
                    resolve(resp)
                 else 
                    reject(err)
                
            ).then(resp => 
                console.log(resp)
                let volData = 
                    name: resp[0].name,
                    exchange_rank: resp[0].exchange_rank,
                    icon: resp[0].icon
                
                return volData
            )
        )
    ))



getSingleExchange().then(data => 
    console.log(data)
);

我现在收到此错误:

(node:30583) UnhandledPromiseRejectionWarning: TypeError: db.connection.query(...).then 不是函数 在承诺 (/getExchanges.js:217:16) 在新的 Promise () 在 Promise.all.exchanges.map (/getExchanges.js:145:16) 在 Array.map() 在 getSingleExchange (/getExchanges.js:144:33)

【问题讨论】:

【参考方案1】:

主要问题在这部分:

await Promise.all(exchanges.map(async (item) => 

那个map回调没有返回任何东西,它没有await,所以使用async没有意义。

改为删除async

await Promise.all(exchanges.map((item) => 

...并在回调函数中返回一个承诺,就像您在第一个函数中所做的那样:

    return new Promise((resolve, reject) => 
        db.connection.query(`...`), (err, resp) => 
            if (!err) 
                resolve(resp)
             else 
                reject(err)
            
        )
    ).then(resp => 
        console.log(resp)
        let volData = 
             name: resp[0].name,
             exchange_rank: resp[0].exchange_rank,
             icon: resp[0].icon
         
         return volData 
    );

您将从编写一个承诺query 的通用函数中受益,这样您就不必为您需要的每个查询都执行new Promise 的事情。

最后,你不能指望同步获得异步结果:async 函数不会同步返回异步结果,而是为它返回一个 Promise。所以你的最后几行(主要代码)应该还在等待。所以要么这样做:

(async () => 
    const data = await getSingleExchange()
    console.log(data)
)(); // immediately executing (async) function expression

或者:

getSingleExchange().then(data => 
    console.log(data)
);

注意:在第二个函数中执行 return await exchanges 毫无意义(exchanges 不是承诺),因此您可以执行 return exchanges

【讨论】:

感谢回复,得到相同的回复 Promise 那是因为你没有等待主代码中的最终承诺(最后两行)。请参阅我的答案。 我按照步骤更改了代码。仍然收到错误。我已经编辑了显示我遇到的错误的代码。 你在哪里做了.query(....).then,正如错误消息中所说的那样?这不在我的回答中。也请不要这样调整您的问题。这让我的回答看起来无关紧要。如果您想为您的问题添加信息,那没关系,但请保留原始问题。注意:您在问题中添加的新代码是 not 就像我在回答中所说的那样。 then 放错地方了。 我修复了这一行中的错误 db.connection.query(...), (err, resp) => (在这里包装了我的数据库查询)。现在 console.log() 正在打印所有值,但使用时返回 volData。显示未定义。我试过 getSingleExchange().then(data => console.log(data) );和 (async () => const data = await getSingleExchange() console.log(data) )();

以上是关于从 Nodejs 中的 mySQL 获取数据时如何从 Async/await 函数获取返回值的主要内容,如果未能解决你的问题,请参考以下文章

当我直接从 MySQL 获取时,NodeJS 响应 MySQL 时区不同

从 NodeJS 中的 AJAX 请求中获取数据并存储在 DB 中

如何创建从 nodejs mysql 模块获取的正确 json 类型数据?

如何从 Nodejs Mysql 获取 JSON 类型作为 JSON 而不是 String

nodejs从MySQL数据中获取的时间,展示时与存储时间相差8小时的解决方法

nodejs从MySQL数据中获取的时间,展示时与存储时间相差8小时的解决方法