Javascript Promise扩展到更多promises会导致不可预测的数据格式(和不可读的代码)

Javascript Promise扩展到更多promises会导致不可预测的数据格式(和不可读的代码),javascript,stack,promise,Javascript,Stack,Promise,我正试图用承诺重写一些“旧”代码。目前,代码使用自己的堆栈,可以从所有回调中访问该堆栈,有时会将新项添加到堆栈中,直到堆栈为空,然后运行最终回调,所有收集的数据的格式都很好(也可以在所有回调中访问) 这里的要点是:stack和data可以从所有回调中访问,因此每个回调都可以通过push添加到data。最终的结果总是一个一维数组 这个过程总是从Promise.all([a,b])开始 a添加到数据中就是这样 b可能会增加数据就是这样,但它更可能产生更多承诺 这些承诺会增加数据和/或产生更多承诺 等

我正试图用承诺重写一些“旧”代码。目前,代码使用自己的堆栈,可以从所有回调中访问该堆栈,有时会将新项添加到堆栈中,直到堆栈为空,然后运行最终回调,所有收集的数据的格式都很好(也可以在所有回调中访问)

这里的要点是:
stack
data
可以从所有回调中访问,因此每个回调都可以通过
push
添加到
data
。最终的结果总是一个一维数组

  • 这个过程总是从
    Promise.all([a,b])开始
  • a
    添加到
    数据中
    就是这样
  • b
    可能会增加
    数据
    就是这样,但它更可能产生更多承诺
  • 这些承诺会增加数据和/或产生更多承诺
  • 等,理论上是有限的,但通常只有1-3层深
  • 对于
    b
    中的每个新生成,前面的结果都是必需的,因此我不能将它们与
    a
    b
    一起启动

    我做了一个简化的演示:(检查控制台并点击空白体再次运行)

    • 有时
      b
      返回标量(立即返回数据)
    • 有时,它会从多个繁殖(数组)返回数据
    • 而且这些繁殖还可能从更多繁殖(更多数组!)返回数据
    因此,数据可以如下所示:

    • [a,b]
    • [a[b,b]]
    • [a[b[c,c,c],[c,c]]]
      (不在演示中,只有两个级别)

    它应该总是像:

    • [a,b,c,c,c,c]
      (1D,任意数量的元素)
    在每次
    then(callback)
    中,我只有
    p.all
    的结果,而不是所有的结果,直到最后一次完成,格式可以是任何东西

    这是处理器:

    console.time('ALL-LOADED');
    Promise.all([local(),sync()]))
    .then(功能(数据){
    //数据[0](来自a)始终是标量
    //数据[1](来自1个或多个b)可能是数组
    if(数据[1]数组实例){
    数据[1]。取消移位(数据[0]);
    返回数据[1];
    }
    返回数据;
    })
    .then(功能(数据){
    console.log('DONE',data);
    console.timeEnd(“全部加载”);
    控制台日志(“”);
    });
    
    如您所见,第一个
    然后(回调)
    将数据格式化为我需要的1D数组。这个很简单,但是级别越多,它就越大

    我的主要问题是:这是正确的方法吗?是否有一个“每次
    之后(回调)
    ”来保持数据的格式设置?或者更好:更容易访问全局
    数据
    ,就像我当前的设置一样

    或者在第一个
    p.all
    堆栈仍在运行时添加到该堆栈?那将是最好的。只有1个
    then(回调)
    和一个
    数据,但大小可变


    承诺很酷,但复杂的东西仍然很复杂,甚至更复杂。

    我以前没有尝试过将承诺与递归结合使用,所以我把它弄得有点乱。我不确定这是否对你有帮助,但对我来说很有趣

    我仍然在努力不使用globalData变量作为累加器,但是在承诺中传递累加器会有点奇怪,我还不知道为什么

    var prom = require('bluebird'),
        _ = require('lodash'),
        globalData = []
    
    /**
     * return a number 1/2 of the time, array rest of the time
     */
    function asyncSometimesArrayDataSource() {
        if (Math.random() > 0.5) {
            return prom.resolve(2);
        } else {
            return prom.resolve([1, 2]);
        }
    };
    
    
    function asyncAlwaysIntDataSource() {
        return prom.resolve(2);
    }
    
    
    function recursivePromises(arr) {
        return prom.all(asyncSometimesArrayDataSource()
            .then(function (data) {
                if (data instanceof Array) {
                    return prom.all(data.map(function (val) {
    
                        globalData.push(val)
                        return recursivePromises();
                    }));
                } else {
                    globalData.push(data);
                    return globalData;
                }
            }));
    
    }
    
    asyncAlwaysIntDataSource()
        .then(function (easyData) {
            return recursivePromises()
                .then(function () {
                    return globalData;
                });
        })
        .then(function (finaldata) {
            console.log('final data', finaldata);
        });
    
    这是先前尝试的改进版本,没有外部累积数组

    var prom = require('bluebird'),
        _ = require('lodash'),
        // count is used to verify that the final array is the correct length
        count = 0;
    
    
    /**
     * return a number 1/2 of the time, array rest of the time
     */
    function asyncSometimesArrayDataSource() {
        if (Math.random() > 0.5) {
            return prom.resolve(2);
        } else {
            return prom.resolve([4, 5]);
        }
    }
    
    
    function asyncAlwaysIntDataSource() {
        count++;
        return prom.resolve(2);
    }
    
    
    
    function recursivePromises(arr) {
        return asyncSometimesArrayDataSource()
            .then(function (data) {
                if (data instanceof Array) {
                    return prom.map(data, function (val) {
                        count++;
                        return recursivePromises([val]);
                    }).then(function (mapdata) {
                        return arr.concat(mapdata);
                    });
                } else {
                    count++;
                    arr.push(data);
                    return arr;
                }
            });
    }
    
    asyncAlwaysIntDataSource()
        .then(function (easyData) {
            return recursivePromises([easyData])
        })
        .then(function (finaldata) {
            console.log('final data', _.flatten(finaldata), count, _.flatten(finaldata).length);
        });
    

    我会使用返回值而不是全局对象来传达对象的行为和返回的内容。这种方法听起来很难同步。另外,我不知道为什么要使用嵌套数组,而不是树,例如,在树上可以实现一个更简单的迭代器?示例plz?(我当前解决方案中的堆栈和数据不是完全全局的,但它们的作用域在所有回调之外。)听起来您需要一个递归函数。@Bergi是的,但我如何向
    数据添加
    并传递承诺?像我现在这样的堆栈不是有更好、更可读的解决方案吗?通常我发现递归比堆栈更容易理解:-)无论如何,您的任务似乎只在堆栈的顶部运行。
    recursivepromissions()
    非常奇怪。您没有使用
    arr
    ,您是否打算将1个承诺(包括
    .then
    )传递到
    prom.all()
    ?我不喜欢
    globalData
    非常=)我很喜欢它由倒数第二个
    then()
    返回的方式,因此它被传递到倒数第二个
    then()。如果只有承诺执行者可以在
    all()
    中附加到承诺列表中。。。从2开始,进行扩展,完成后得到1个结果。啊,但愿如此。是的,在原始答案中留下arr是一个拼写错误。我仍然不确定更新后的答案是否更适合您,但我很高兴找到了一种方法,使递归能够在承诺的基础上工作一点。arr.concat(mapdata)部分似乎仍然有点笨拙,但我不知道如何绕过它。