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
可能会增加数据
就是这样,但它更可能产生更多承诺b
中的每个新生成,前面的结果都是必需的,因此我不能将它们与a
和b
一起启动
我做了一个简化的演示:(检查控制台并点击空白体再次运行)
- 有时
返回标量(立即返回数据)b
- 有时,它会从多个繁殖(数组)返回数据
- 而且这些繁殖还可能从更多繁殖(更多数组!)返回数据
[a,b]
[a[b,b]]
(不在演示中,只有两个级别)[a[b[c,c,c],[c,c]]]
(1D,任意数量的元素)[a,b,c,c,c,c]
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)部分似乎仍然有点笨拙,但我不知道如何绕过它。