Javascript функция завершена из-за асинхронности - PullRequest
0 голосов
/ 11 января 2020

У меня есть простая функция, которая вызывает коллекцию пожарных и возвращает список компаний. Я перебираю список и выводю название компании. Как только все будет готово, я хочу написать «готово».

function getCompanies() {
    firestore.collection('companies')
        .listDocuments()
        .then(companies => {
            for(var i in companies) {
                companies[i].get().then(company => {
                    console.log(company.name);
                });
            }
        }).catch(err => {
        console.error(err);
    });
};

getCompanies();
console.log('done');

На самом деле, вот что происходит ...

done
ford
gm
toyota
jeep
vw

Я посмотрел на обещания ...

function getCompanies() {
    firestore.collection('companies')
        .listDocuments()
        .then(companies => {
            let promises = [];

            for(var i in companies) {
                companies[i].get().then(company => {
                    promises.push(doIt(company.id));
                });
            }

            Promise.all(promises)
                .then((results) => {
                console.log("All done", results);
                })
                .catch((e) => {
                    // Handle errors here
                });

        }).catch(err => {
        console.error(err);
    });
};

function doIt(value) {
    return new Promise((resolve) => {
    setTimeout(() => {
        console.log(value);
        resolve(value);
    }, Math.floor(Math.random() * 1000));
    });
}

getCompanies();

Но это тоже не сработало ...

All done []
ford
gm
toyota
jeep
vw

Есть советы или советы? Я чувствую, что забыл сделать что-то очевидное: /.

Заранее спасибо!

Ответы [ 3 ]

4 голосов
/ 11 января 2020

Это потому, что console.log является синхронным, а getCompanies () - асинхронным. GetCompanies разрешится в будущем. Прочтите немного об Promise и async / await.

Быстрое исправление без использования async / await будет:

function getCompanies() {
    return firestore.collection('companies')
        .listDocuments()
        .then(companies => {
            const promises = [];
            for(var i in companies) {
                promises.push(companies[i].get());
            }
            return Promise.all(promises);
        }).catch(err => {
        console.error(err);
    });
};

Теперь запустите getCompanies и console.log по порядку , вам нужно выполнить console.log после разрешения getCompanies

getCompanies()
.then((companiesarr)=>{
    companiesarr.forEach((c)=>{
        console.log(c.name)
    })
}).then(()=>console.log('done'))
0 голосов
/ 11 января 2020

Это отличный обзор обещаний, который объясняет, какие блоки кода являются асинхронными.

https://levelup.gitconnected.com/async-await-vs-promises-4fe98d11038f

Если вы хотите, чтобы «готово» печаталось в В правильном порядке он должен вызываться в блоке asyn c.

Если я правильно понимаю, .get () возвращает обещание, поэтому вам нужно будет сделать что-то подобное.

function getCompanies() {
  firestore
    .collection('companies')
    .listDocuments()
    .then(companies => {
      const myPromisesArr = companies.map(i => i.get());

      Promises.all(myPromisesArr).then(companies => {
        companies.forEach(company => {
          console.log(company.id);
        });
      });
    })
    .catch(error => console.error(error))

    .finally(() => console.log(`done`));
}
0 голосов
/ 11 января 2020

Вам нужно вернуть промис из вашей функции следующим образом

function getCompanies() {
    return firestore.collection('companies')
        .listDocuments()
        .then(companies => {
            for(var i in companies) {
                companies[i].get().then(company => {
                    console.log(company.name);
                });
            }
        }).catch(err => {
        console.error(err);
    });
};

...