Функция JavaScript Promise возвращается слишком рано - PullRequest
2 голосов
/ 17 октября 2019

Я выполняю кучу функций обещания, а затем возвращаю разрешенные массивы. Однако при возврате массивов он возвращает неопределенное значение. Если я использую setInterval для выполнения через 3 секунды, массивы возвращают значения.

Вот код:

function getData() {
    var a = new Promise((resolve, reject) => {
        getDressData().then(function(result) {
            resolve(result);
            console.log('promise a resolved');
        });
    });

    var b = a.then(function(result) {
        var dressOwners = result.dressOwners;
        return new Promise((resolve, reject) => {
            getOwnerData(dressOwners).then(function(result) {
                resolve(result);
                console.log('promise b resolved');
            });
        });
    });

    return Promise.all([a, b])
    .then(function([resultA, resultB]) {
        if (resultA) {
            if (resultB) {
                console.log('promise all resolved');
                return resultA;
            }
        }
    });
}

Чтобы вернуть массивы:

function getDreses() {
    getData().then(function(result) {
        console.log('Returning promise...');
        console.log(result.dresses[1].colour);
    });
}

Результат:

обещание решено - main.js: 679
обещание b решено - main.js: 688
обещание все решено - main.js: 697
Возвращение обещания ... - main.js: 706
Uncaught (в обещании) TypeError: Невозможно прочитать свойство 'color' undefined в main.js: 707


Однако, если я установлю задержку в 3 секунды перед получением каких-либо значений из массива, это сработает!

function getDreses() {
    getData().then(function(result) {
        var t = setInterval(() => {
            dresses = result.dresses;
            console.log(dresses.length);
            console.log(dresses[1].colour);
            clearInterval(t);
        }, 3000);
    });
}

Результат:

обещание решено - main.js: 679
обещание b решено - main.js: 688
обещание все решено - main.js: 697
возвращение обещания ... - main.js: 706
4 - main.js: 711
синий - main.js: 712



Итак, как мне подождать, пока массивы не будут иметь значения, вместо ожидания с задержкой в ​​3 секунды?



Редактировать (Может быть проблема с getDressData() разрешается слишком быстро):

function getDressData() {
    return new Promise((resolve, reject) => {
        var db = firebase.firestore();
        var dresses = [];
        var filters = [];
        var dressOwners = [];
        
        db.collection('dresses').orderBy("date", "desc")
        .get().then(function(doc) {       
            doc.docs.forEach(function(doc) {
                var item = doc.data();
                dresses.push({
                    'dressId' : doc.id,
                    'colour' : item.colour,
                    'credit' : item.credit,
                    'date' : item.date,
                    'description' : item.description,
                    'images' : item.images,
                    'owner' : item.owner,
                    'size' : item.size
                });

                if(filters.filter(x => x.size == item.size).length == 0) {
                    filters.push({"size" : item.size, "colours": [item.colour]});
                } 
                else {
                    var index = filters.findIndex((x => x.size == item.size));
                    
                    if (!filters[index].colours.filter(x => x.colours == item.colour).length > 0) {
                        filters[index].colours.push(item.colour);
                    }
                }

                if (dressOwners.indexOf(item.owner) === -1) {
                    dressOwners.push(item.owner);
                }
            });
        });

        resolve({
            "dresses" : dresses,
            "filters" : filters,
            "dressOwners" : dressOwners
        });
    });
}

1 Ответ

1 голос
/ 17 октября 2019

Точно этот фрагмент неправильный. (См. Комментарии в коде)

function getDressData() {
    return new Promise((resolve, reject) => {
        var db = firebase.firestore();
        var dresses = [];
        var filters = [];
        var dressOwners = [];
        

        /*
         * this is a promise from your db
         */
        db.collection('dresses').orderBy("date", "desc")
        .get().then(function(doc) {       
            doc.docs.forEach(function(doc) {
                var item = doc.data();
                dresses.push({
                    'dressId' : doc.id,
                    'colour' : item.colour,
                    'credit' : item.credit,
                    'date' : item.date,
                    'description' : item.description,
                    'images' : item.images,
                    'owner' : item.owner,
                    'size' : item.size
                });

                if(filters.filter(x => x.size == item.size).length == 0) {
                    filters.push({"size" : item.size, "colours": [item.colour]});
                } 
                else {
                    var index = filters.findIndex((x => x.size == item.size));
                    
                    if (!filters[index].colours.filter(x => x.colours == item.colour).length > 0) {
                        filters[index].colours.push(item.colour);
                    }
                }

                if (dressOwners.indexOf(item.owner) === -1) {
                    dressOwners.push(item.owner);
                }
            });
        });

        /*
         * and you're resolving this function outside the db promise.
         * this will resolve before the db-promise finished
         */
        resolve({
            "dresses" : dresses,
            "filters" : filters,
            "dressOwners" : dressOwners
        });
    });
}

Вы можете попробовать использовать async / await, может быть, его лучше понять. вот так:

// with async, this function will return a promise
// just use it like a promise: getDressData().then(/*...*/)

async function getDressData() {
        var db = firebase.firestore();            

        return await db.collection('dresses').orderBy("date", "desc")
        .get().then(function(doc) {  
            
            // process your db-response

            var dresses = [];
            var filters = [];
            var dressOwners = [];

            doc.docs.forEach(function(doc) {
                var item = doc.data();
                dresses.push({
                    'dressId' : doc.id,
                    'colour' : item.colour,
                    'credit' : item.credit,
                    'date' : item.date,
                    'description' : item.description,
                    'images' : item.images,
                    'owner' : item.owner,
                    'size' : item.size
                });

                if(filters.filter(x => x.size == item.size).length == 0) {
                    filters.push({"size" : item.size, "colours": [item.colour]});
                } 
                else {
                    var index = filters.findIndex((x => x.size == item.size));
                    
                    if (!filters[index].colours.filter(x => x.colours == item.colour).length > 0) {
                        filters[index].colours.push(item.colour);
                    }
                }

                if (dressOwners.indexOf(item.owner) === -1) {
                    dressOwners.push(item.owner);
                }

                return {
                   dresses,
                   filters,
                   dressOwners
                }
            });
        });
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...