跳过JavaScript多级承诺.then() [英] JavaScript multi-level promises skipped .then()

查看:75
本文介绍了跳过JavaScript多级承诺.then()的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我遇到了多层承诺的问题。我试图做的是首先得到某些类别下的收据项目清单,然后对于每个收据项目,我得到它的详细信息和收据ID,收到收据ID后,我搜索帐户ID。然后,我根据帐户ID获取帐户详细信息。这是我的代码:

I was having some problem with multi-level of promises. What I tried to do is first get list of receipt items under certain category, then for each receipt item, I get its detail & receipt ID, after I get the receipt ID, I search for the account ID. Then, I get the account details based on account ID. Here is my code:

var query =  // get receipt items under certain category
    var outerPromise = query.once('value').then(data => {
        var promises = [];
        var datasetarr = [];

        data.forEach(snapshot => {
            var itemData = // get receipt item unique push ID

            var query = // get details of receipt items 
            var promise = query.once('value').then(data => { 
                var itemDetail = // get receipt item detail

                if(type == subtype){    
                    var receiptID = itemDetail.receiptID;

                    var query = // query receipts table by receiptID
                    return query.once('value').then(data => {   
                        data.forEach(snapshot => {
                            snapshot.forEach(childSnapshot => {
                                if(childSnapshot.key == receiptID){
                                    var accountKey = // get accountID

                                    var query = // query accounts table
                                    return query.once('value').then(data => {
                                        var accountDetail = data.val();
                                        var age = accountDetail.age;
                                        var gender = accountDetail.gender;
                                        console.log(age + ' ' + gender);
                                        datasetarr.push({age: age, gender: gender});
                                    });
                                }
                            });
                        });
                    }); 
                }
            });
            promises.push(promise);
        }); 

        return Promise.all(promises).then(()=> datasetarr);
});

我设法打印出 console.log 以上。但是,当我试图在这里打印出承诺时:

I managed to print out the result from the console.log above. However, when I tried to print out here which is when the promise is done:

outerPromise.then((arr) => {
        console.log('promise done');
        for(var i = 0; i < arr.length; i++){
            console.log(arr[i].age + ' ' + arr[i].gender);
        }
    }); 

我什么都没得到。在我上面打印出的任何其他结果之前,控制台现在首先显示承诺完成。

I get nothing here. The console now is showing 'promise done' first before any other results I printed out above.

任何想法?谢谢高级!

推荐答案


我会在几个小时内提供更详细的解释,我事先约定,这意味着我现在无法提供详细信息

I will provide a more detailed explanation in a couple of hours, I have a prior engagement which means I can't provide details now

简单解决方案的第一步是创建一个函数从firebase快照中创建一个数组,因此我们可以使用map / concat / filter等。

First step to a "easy" solution is to make a function to make an array out of a firebase snapshot, so we can use map/concat/filter etc

const snapshotToArray = snapshot => {
    const ret = [];
    snapshot.forEach(childSnapshot => {
        ret.push(childSnapshot);
    });
    return ret;
};

现在,代码可以写成如下

Now, the code can be written as follows

// get list of receipt items under category
var query // = // get receipt items under certain category
var outerPromise = query.once('value').then(data => {
    return Promise.all(snapshotToArray(data).map(snapshot => {
        var itemData // = // get receipt item unique push ID
        var query // = // get details of receipt items 
        return query.once('value').then(data => { 
            var itemDetail // = // get receipt item detail
            if(type == subtype){    
                var receiptID = itemDetail.receiptID;
                var query //= // query receipts table by receiptID
                return query.once('value').then(data => {   
                    return Promise.all([].concat(...snapshotToArray(data).map(snapshot => {
                        return snapshotToArray(snapshot).map(childSnapshot => {
                            if(childSnapshot.key == receiptID){
                                var accountKey //= // get accountID
                                var query //= // query accounts table
                                return query.once('value').then(data => {
                                    var accountDetail = data.val();
                                    var age = accountDetail.age;
                                    var gender = accountDetail.gender;
                                    console.log(age + ' ' + gender);
                                    return({age, gender});
                                });
                            }
                        }).filter(result => !!result);
                    }).filter(result => !!result)));
                }); 
            }
        });
    })).then([].concat(...results => results.filter(result => !!result))); 
});

在评论中解释问题

[]。concat 用于将多个数组的内容添加到新数组,即

[].concat used to add the content of multiple arrays to a new array, i.e

[].concat([1,2,3],[4,5,6]) => [1,2,3,4,5,6]

.. .snapshotToArray(data).map(etc

...是扩展运算符,用作函数的参数,它需要可迭代并将其传播到多个参数

... is the spread operator, used as an argument to a function, it takes the iterable and "spreads" it to multiple arguments

console.log(...[1,2,3]) == console.log(1,2,3)

在这种情况下 snapshotToArray( data。.map 返回一个数组数组,给出一个控制台日志示例

In this case snapshotToArray(data).map returns an array of arrays, to give a console log example

console.log(...[[1,2],[3,4]]) == console.log([1,2], [3,4])

添加concat

[].concat(...[[1,2],[3,4]]) == [].concat([1,2],[3,4]) == [1,2,3,4]

因此它将两级数组展平为单一级别,即

so it flattens a two level array to a single level, i.e.

console.log(...[[1,2],[3,4]]) == console.log(1,2,3,4)

总而言之,该代码片段所做的是将两级数组展平

So in summary, what that code fragment does is flatten a two level array

filter(result => !!result)

简单地过滤任何假的数组元素。因为你有这个条件

simply "filters" out any array elements that are "falsey". As you have this condition

if(childSnapshot.key == receiptID){

如果为false,那么地图的结果将是 undefined - 所有其他结果都是一个数组,甚至空数组都是真的 - 这就是为什么过滤经常这样做的原因!可能有更好的方法来完成所有这些,但除非你要处理数百万项,否则过滤空结果就没有真正的问题

if that is false, the result will be undefined for that map - all other results will be an array, and even empty arrays are truthy - that's why the filtering is done so often! There's probably a better way to do all that, but unless you're dealing with literally millions of items, there's no real issue with filtering empty results like this

最终结果是一个平面数组,只有从

End result is a flat array with only the Promises returned from the code within

这篇关于跳过JavaScript多级承诺.then()的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆