JavaScript承诺不使用resolve()

时间:2017-07-31 06:46:39

标签: javascript arrays for-loop asynchronous promise

我在JavaScript中承诺存在一些问题。所以我想要做的是我想从firebase中检索,然后将所有返回的结果存储到数组中。之后,我将对阵列执行一些排序。这是我的代码:

    let promise = new Promise((resolve, reject) => {
    var query = firebase.database().ref('');
        query.once( 'value', data => {
            data.forEach(subtypeSnapshot => {
                var itemData = ;

                var query = firebase.database().ref('').child(itemKey);
                query.once( 'value', data => {
                    var itemDetail = ;
                    datasetarr.push();
                });
            }); 
            resolve(datasetarr);
        });             
    });

使用这组代码,从promise中的第一个console.log开始,我设法在我的控制台中获取这些代码:

有了这些,这意味着我的firebase检索没有任何问题。之后,我想将它们中的每一个存储到数组中,这就是它的一部分:

datasetarr.push({type: subtype, quantity: quantity});

完成所有事情后我解决了承诺,当承诺完成后,我打印出数组中的项目。但是,.then()内的for循环中没有打印出任何内容。有什么想法吗?

3 个答案:

答案 0 :(得分:1)

正如已经提到的:你的承诺太早解决了。

在解析包装Promise之前,您可以使用Promise.all等待所有承诺解决。我把一个简单的例子放在一起,但由于缺少firebase数据库,我只使用返回Promises的函数:https://jsfiddle.net/57b0gkLt/

根据firebase documentationquery.once('value')会返回一个承诺,所以这应该有效。

编辑:喜欢这个

var datasetarr = [];
let promiseItemDataList = new Promise((resolve, reject) => {
var query = firebase.database().ref('receiptItemIDsByCategory').child(category);
    query.once( 'value', data => {
        var promises = []; // NEW LINE

        data.forEach(subtypeSnapshot => {
            var itemData = subtypeSnapshot.val();
            var itemKey = subtypeSnapshot.key;

            var query = firebase.database().ref('receiptItems').child(itemKey);
            var promise = query.once('value'); // NEW LINE
            promises.push(promise); // NEW LINE

            promise.then(data => { // .then instead of a callback
                var itemDetail = data.val();
                var subtype = itemDetail.type;
                var quantity = itemDetail.quantity;
                console.log('inside promise ' + subtype + ' ' + quantity);
                datasetarr.push({type: subtype, quantity: quantity});
            });
        }); 

        Promise.all(promises).then(() => resolve(datasetarr)); // NEW LINE
    });             
});

promiseItemDataList.then((arr) => {
    for(var i = 0; i < arr.length; i++){
        console.log('outside promise ' + arr[i].type + ' ' + arr[i].quantity);
    }
});

答案 1 :(得分:1)

您正在正确处理检索初始数据集的第一次async调用,但未处理.forEach循环调用的后续调用。

query.once( 'value', data => {
    var itemDetail = data.val();
    var subtype = itemDetail.type;
    var quantity = itemDetail.quantity;
    console.log('inside promise ' + subtype + ' ' + quantity);
    datasetarr.push({type: subtype, quantity: quantity});
});

麻烦的是,在返回其他异步调用之前,你是resolving承诺。

我不确定query.once处理callback的确切程度。它看起来不像是承诺也不是传统的callback function方式。

work-around可以做的是将forEach.async调用包装到Promise对象中,然后使用Promise.all([list_of_promises])触发一组promises以确保每一个在主要承诺resolving之前返回单个呼叫。

伪码:

var datasetarr = [];
let promiseItemDataList = new Promise((resolve, reject) => {
    var query = firebase.database().ref('receiptItemIDsByCategory').child(category);
    query.once( 'value', data => {

        // Collect a list of promises for the sub item async calls
        var get_data_promises = [];
        data.forEach(subtypeSnapshot => {
            get_data_promises.push(new Promise(function(resolve) {
                var itemData = subtypeSnapshot.val();
                var itemKey = subtypeSnapshot.key;
                var query = firebase.database().ref('receiptItems').child(itemKey);

                query.once( 'value', data => {
                    var itemDetail = data.val();
                    var subtype = itemDetail.type;
                    var quantity = itemDetail.quantity;
                    console.log('inside promise ' + subtype + ' ' + quantity);
                    datasetarr.push({type: subtype, quantity: quantity});
                    resolve("Done");
                });
        }))

        // Fire them all - Once done resolve the main promise.
        Promise.all(get_data_promises).done(function() { resolve(datasetarr); });
    });
});

答案 2 :(得分:1)

var query = firebase.database().ref('receiptItemIDsByCategory').child(category);

query.once('value')
.then((data) => {
    promises =[]
    data.forEach( subtypeSnapshot => {
        var itemData = subtypeSnapshot.val();
        var itemKey = subtypeSnapshot.key;

        var query = firebase.database().ref('receiptItems').child(itemKey);
        p = query.once( 'value', data => {
                    var itemDetail = data.val();
                    var subtype = itemDetail.type;
                    var quantity = itemDetail.quantity;
                    console.log('inside promise ' + subtype + ' ' + quantity);
                });
        promises.push(p)
    })
    return promises
})
.then ((arrayofpromises) => {
    Promise.all(arrayofpromises)
    .then((results)=>{
        console.log(results)
    })
})