Async / await в Firebase Cloud Function сообщает, что выражение ошибки имеет тип `void` - PullRequest
0 голосов
/ 20 декабря 2018

Я пытаюсь использовать async / await в своей функции firebase, но получаю ошибку.Я пометил функцию как асинхронную, но когда я пытаюсь использовать внутри нее await, я получаю сообщение об ошибке: Выражение имеет тип void.Поместите его в отдельную строку как выражение.

Я думаю, что это странно, потому что я думаю, что каждый вызов функции await уже находится в отдельной строке в качестве выражения.Так что я не уверен, что делать.Буду признателен за любую помощь.

Для ясности я делаю запрос с библиотекой веб-очистки Cheerio, а затем пытаюсь сделать два вызова асинхронных функций во время каждого цикла с помощью метода .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 голосов
/ 25 апреля 2019

на всякий случай, если кто-то придет.Как уже говорил Рон, вы не должны использовать async/await внутри традиционного цикла for, если второй вызов не нуждается в значении первого, поскольку вы увеличите время выполнения кода.

Более того, вы не можете использовать async/await внутри цикла forEach=> или map=>, так как он не остановится и не дождется выполнения обещания.

НаиболееЭффективным способом является использование Promise.all([]).Здесь я оставляю отличное видео на YouTube, в котором объясняются async/await и обещания => https://www.youtube.com/watch?v=vn3tm0quoqE&t=6s

Что касается одного из вопросов в комментариях DarkHorse:

Новсе, что я хочу, - это чтобы getTeamPlayers () выполнялся и записывал в базу данных, поэтому я не знаю, зачем мне что-либо возвращать.

В функциях Firebase все функции должны возвращать что-то до окончательного ответа,

Например, в этом случае он создал функцию http.Прежде чем он завершит функцию с response.send("retrieved schedule");, вам нужно завершить каждую сработавшую функцию.Поскольку Firebase Functions очищается после финального response, стирает и останавливает все, что еще работает.Таким образом, любая функция, которая не завершится, будет уничтожена перед выполнением своей работы.

Возврат обещания - это способ, которым Firebase Functions знает, когда все выполнения завершены, и может очистить.

Прыгайте, это помогает:)

0 голосов
/ 20 декабря 2018

async/await поддерживается в Node версии 8 (которая может быть развернута как облачные функции для Firebase).В частности, используйте 8.6.1 (на момент написания этой статьи).

Что касается ожидания x2 внутри цикла - я не думаю, что это лучшая практика.

Вместо этого, нажмите все этизапросы в массив, затем Promise.all, чтобы получить все параллельно.

...