Firebase Cloud Function中的Async / await表示错误表达式的类型为“ void”

时间:2018-12-20 15:26:11

标签: javascript firebase async-await google-cloud-functions

我正在尝试在Firebase函数中使用async / await,但出现错误。我已将该函数标记为异步,但是当我尝试在其中使用await时,出现错误:表达式的类型为void。将该语句放在一行上。

我认为这很奇怪,因为我认为每个await函数调用已经作为语句在其自己的行中。因此,我不确定该怎么办。任何帮助将不胜感激。

为清楚起见,我正在向Cheerio Web scrape库发出请求,然后尝试在每个循环期间使用.each方法进行两次异步函数调用。

export const helloWorld = functions.https.onRequest((req, response) => {


const options = {
uri: 'https://www.cbssports.com/nba/scoreboard/',
transform: function (body) {
    return cheerio.load(body);
}
};

request(options)
.then(($) => {


$('.live-update').each((i, element) => {

        const homeTeamAbbr = $(element).find('tbody').children('tr').eq(0).find('a').html().split("alt/").pop().split('.svg')[0];
        const awayTeamAbbr = $(element).find('tbody').children('tr').eq(1).find('a').html().split("alt/").pop().split('.svg')[0];
        const homeTeam = $(element).find('tbody').children('tr').eq(0).find('a.team').text().trim();
        const awayTeam = $(element).find('tbody').children('tr').eq(1).find('a.team').text().trim();
        let homeTeamStatsURL = $(element).find('tbody').children('tr').eq(0).find('td').html();
        let awayTeamStatsURL = $(element).find('tbody').children('tr').eq(1).find('td').html();
        const gameTime = $(element).find('.pregame-date').text().trim();

        homeTeamStatsURL = homeTeamStatsURL.match(/href="([^"]*)/)[1] + "roster";
        awayTeamStatsURL = awayTeamStatsURL.match(/href="([^"]*)/)[1] + "roster";

        const matchupString = awayTeamAbbr + "@" + homeTeamAbbr;
        const URLString = "NBA_" + urlDate + "_" + matchupString;
        // var docRef = database.collection('NBASchedule').doc("UpcommingSchedule");
        // var boxScoreURL = "www.cbssports.com/nba/gametracker/boxscore/" + URLString;

        // var setAda = docRef.set({[URLString]:{
        //   homeTeam: homeTeam,
        //   awayTeam: awayTeam,
        //   date: gameTime,
        //   homeTeamAbbr: homeTeamAbbr,
        //   awayTeamAbbr: awayTeamAbbr,
        //   homeTeamStatsURL: homeTeamStatsURL,
        //   awayTeamStatsURL: awayTeamStatsURL,
        //   boxScoreURL: boxScoreURL
        // }}, { merge: true });

         getTeamPlayers(homeTeamStatsURL, matchupString);
         getTeamPlayers(awayTeamStatsURL, matchupString);

        console.log("retrieved schedule for "+ matchupString + " on " + urlDate)



});

 response.send("retrieved schedule");
})
.catch(function (err) {
   console.log("error " + err);
});

});

我正在调用的函数只是发出另一个请求,然后试图记录一些数据。

function getTeamPlayers(playerStatsURL, matchupString) {


const options = {
    uri: playerStatsURL,
    transform: function (body) {
        return cheerio.load(body);
    }
};

 console.log(playerStatsURL + " stats url");

request(options)

.then(($) => {

    console.log('inside cheerio')

     $('tbody').children('tr').each(function(i, element){

        const playerName = $(element).children('td').eq(1).children('span').eq(1).find('a').text().trim();

        const injury = $(element).children('td').eq(1).children('span').eq(1).children('.icon-moon-injury').text().trim();
        const news = $(element).children('td').eq(1).children('span').eq(1).children('.icon-moon-news').text().trim();

        const playerUrl = $(element).children('td').eq(1).children('span').eq(1).find('a').attr('href');
        const playerLogsUrl = "https://www.cbssports.com" + playerUrl.replace('playerpage', 'player/gamelogs/2018');

        console.log(playerName + ": Inj: " + injury + " News: " + news);



        // database.collection('NBAPlayers').add({[playerName]:{
        //   '01 playerName': playerName,
        //   '03 playerLogsUrl': playerLogsUrl,
        //   '04 inj': injury,
        //   '05 news': news

        // }})
      //   .then(docRef => {

      //     console.log("ID " + docRef.id);
      //     //getPlayerLogs(playerLogsUrl, playerName, docRef.id);

      //   })
      //   .catch(error => console.error("Error adding document: ", error));
       });

});

}

2 个答案:

答案 0 :(得分:0)

节点版本8(可以部署为Firebase的Cloud Functions)支持

async/await。具体来说,请使用8.6.1(在撰写本文时)。

关于在循环中等待x2-我认为这不是最佳实践。

相反,将所有这些请求推送到一个数组中,然后Promise.all,以便并行获取所有请求。

答案 1 :(得分:0)

以防万一有人跟进。如Ron之前所述,如果第二个调用不需要第一个调用的值,则不应在传统的for循环中使用async/await,因为这会增加代码的运行时间。

此外,您不能在async/awaitforEach=>循环中使用map=>,因为它不会停止并等待承诺解决。

最有效的方法是使用Promise.all([])。在这里,我留下了一段很棒的youtube视频,上面有一条裂缝,解释了async/await和Promises => https://www.youtube.com/watch?v=vn3tm0quoqE&t=6s

关于DarkHorse评论中的一个问题:

  

但是我只想让getTeamPlayers()执行并写入数据库,所以我不知道为什么我需要返回任何东西。

在Firebase函数中,所有函数都需要在最终响应之前返回某些内容。

例如,在这种情况下,他创建了一个http函数。在他以response.send("retrieved schedule");结尾的函数之前,您需要完成每个触发的函数。由于Firebase Functions将在最后的response之后清理,因此会擦除并停止所有仍在运行的东西。因此,任何尚未完成的功能都将在执行其工作之前被杀死。

“兑现承诺”是Firebase Functions知道所有执行何时完成并可以清除的方式。

希望对您有所帮助:)