嵌套的 For 循环转换为嵌套的 Promises
Nested For Loops converted to Nested Promises
我 运行 遇到了一个问题,我的程序仅在 nameList
的一次迭代中结束,我不确定不合逻辑的代码在哪里。
全球给予:
var _ = require("underscore");
var nameList = ["Bob", "Susie"]
var jsonDict = {}
我复杂的嵌套从这里开始,但我不确定如何修复它,以便它遍历 nameList
和数字 for-loop 1-10
:
return new Promise((res, rej) => {
var promises = [];
return Promise.map(nameList, function(personName){
for (var j=1; j<=10; j++){
return promises.push(new Promise(function(resolve, reject) {
params['page'] = j;
console.log('PAGE ' + j + ' ' + personName)
SOME_SEARCH_FX_THAT_RETURNS_A_PROMISE(params).then(function(data){
return Promise.map(data, function(item, index){
if (!_.has(jsonDict, item.key)){
jsonDict[item.key] = {
name: personName
}
}
return
}).then(function(){
console.log(jsonDict)
return resolve(true)
})
}).catch(function(err){
console.log(err)
return reject(false)
})
}))
}
}).then(function(){
return res(true)
})
}).then(function(){
console.log('Done with everything.')
})
我得到以下输出:
PAGE 1 Bob
PAGE 1 Susie
Done with everything.
{
'12345': { name: "Bob" },
'12346': { name: "Bob" },
...
'99999': { name: "Bob" }
}
而且我从来没有得到 Susie
的数据,我很早就回来了,但似乎无法弄清楚在哪里。任何 help/guidance 问题所在(或什至重构)将不胜感激。提前致谢!
第一:您的代码存在根本性缺陷
为什么我说根本上有缺陷是因为你似乎误解了 functions
的工作原理
return Promise.map(nameList, function(personName){ <-- this function
for (var j=1; j<=10; j++){
return promises.push(new Promise(function(resolve, reject) { <-- is returning HERE
此处Array.prototype.push
函数返回新添加项的index
。 (我查了一下,直到)
这里最大的问题是你返回它。
一旦你 return
Promise.map
的 mapper
函数,你就告诉它你完成了!所以在你上面的代码中,它甚至不会进入 for loop
的下一次迭代
在 MDN 中查找规范以了解 return
它的说法
The return statement ends function execution and specifies a value to be returned to the function caller.
希望这能回答您提早返回的问题。
第二:我不会指望你的承诺
我自己也很难兑现承诺。让我引导您阅读我最近阅读的 awesome articles on promises。现在让我应用我从中学到的东西。谢谢你的提问。
我们承诺要兑现callback hell,但你却歪曲了所有承诺。
我会尝试从最嵌套的部分开始压平 promise
SOME_SEARCH_FX_THAT_RETURNS_A_PROMISE(params).then(function(data){
return Promise.map(data, function(item, index){
if (!_.has(jsonDict, item.key)){
jsonDict[item.key] = {
name: personName
}
}
return
}).then(function(){
console.log(jsonDict)
return resolve(true)
})
}).catch(function(err){
console.log(err)
return reject(false)
})
此处的内部承诺映射是不必要的,您甚至可以对 for loop
使用标准 map
,因为您实际上并未在此处映射任何内容...
[重构 1]
// Create subroutine, careful with the globals...
let populateJsonDict = singleData => {
if (!_.has(jsonDict, singleData.key)) jsonDict[singleData.key] = { name: personName }
}
SOME_SEARCH_FX_THAT_RETURNS_A_PROMISE(params).then(data => {
data.forEach(populateJsonDict);
resolve(true); // this will be removed later
}).catch(function(err){
console.log(err);
reject(false); // this will be removed later
})
好吧,让我们向上移动回调金字塔(或向下移动?)。下一个
for (var j=1; j<=10; j++){
return promises.push(new Promise(function(resolve, reject) {
params['page'] = j;
console.log('PAGE ' + j + ' ' + personName)
//[Refactored 1]
}))
}
这里又是一个不必要的 Promise,是时候摆脱它了。而这里问题的基石,return
[重构 2]
for (var j=1; j<=10; j++){
//[from Refactored 1]
let populateJsonDict = singleData => {
if (!_.has(jsonDict, singleData.key)) jsonDict[singleData.key] = { name: personName }
}
params['page'] = j; // I assume this a global somewhere
let p = SOME_SEARCH_FX_THAT_RETURNS_A_PROMISE(params).then(data => {
data.forEach(populateJsonDict);
// Removed because we've removed the parent promise
}).catch(function(err){
console.log(err);
// Removed because we've removed the parent promise
})
promises.push(p)
}
我会快进,因为我注意到这真的很长。下一个要重构的部分
return new Promise((res, rej) => {
var promises = [];
return Promise.map(nameList, function(personName){
//[Refactored 2]
}).then(function(){
return res(true)
})
}).then(function(){
console.log('Done with everything.')
})
我真的不知道如何挽救这个,所以我会从小组开始写东西。
[重构 3:final]
var promises = [];
nameList.forEach(personName => { // Like earlier, redundant Promise.map
//[from Refactored 2]
for (var j=1; j<=10; j++){
let populateJsonDict = singleData => {
if (!_.has(jsonDict, singleData.key)) jsonDict[singleData.key] = { name: personName }
}
params['page'] = j;
let p = SOME_SEARCH_FX_THAT_RETURNS_A_PROMISE(params).then(data => {
data.forEach(populateJsonDict);
}).catch(function(err){
console.log(err);
})
promises.push(p)
}
});
// At this point you have an array of Promises, for this we can utilize Promise.all
Promise.all(promises)
.then(() => console.log('Done with Everything'));
我想这本可以做得更好。让我做最后一个版本。
[重构 3.1:final]
let populateJsonDict = name => key => !_.has(jsonDict, key) && Object.assign(jsonDict, {[key]:name};
let promises = _.times(10,
index => {
params['page'] = index+1;
return Promise.map(nameList, name => {
let populateWithName = populateJsonDict(name);
let iterate = data => data.forEach(populateWithName);
return SOME_SEARCH_FX_THAT_RETURNS_A_PROMISE(params)
.then(iterate)
.catch(err => console.log(err));
});
});
Promise.all(promises)
.then(() => console.log('Everything done'));
好吧,仍然有这种不满意的感觉,但这就是我现在所拥有的......这对我来说真的比你更重要。所以再次感谢你的朋友。我希望我们都能继续推进这个不断变化的工作领域。抱歉,如果这一切听起来都居高临下。干杯!
我 运行 遇到了一个问题,我的程序仅在 nameList
的一次迭代中结束,我不确定不合逻辑的代码在哪里。
全球给予:
var _ = require("underscore");
var nameList = ["Bob", "Susie"]
var jsonDict = {}
我复杂的嵌套从这里开始,但我不确定如何修复它,以便它遍历 nameList
和数字 for-loop 1-10
:
return new Promise((res, rej) => {
var promises = [];
return Promise.map(nameList, function(personName){
for (var j=1; j<=10; j++){
return promises.push(new Promise(function(resolve, reject) {
params['page'] = j;
console.log('PAGE ' + j + ' ' + personName)
SOME_SEARCH_FX_THAT_RETURNS_A_PROMISE(params).then(function(data){
return Promise.map(data, function(item, index){
if (!_.has(jsonDict, item.key)){
jsonDict[item.key] = {
name: personName
}
}
return
}).then(function(){
console.log(jsonDict)
return resolve(true)
})
}).catch(function(err){
console.log(err)
return reject(false)
})
}))
}
}).then(function(){
return res(true)
})
}).then(function(){
console.log('Done with everything.')
})
我得到以下输出:
PAGE 1 Bob
PAGE 1 Susie
Done with everything.
{
'12345': { name: "Bob" },
'12346': { name: "Bob" },
...
'99999': { name: "Bob" }
}
而且我从来没有得到 Susie
的数据,我很早就回来了,但似乎无法弄清楚在哪里。任何 help/guidance 问题所在(或什至重构)将不胜感激。提前致谢!
第一:您的代码存在根本性缺陷
为什么我说根本上有缺陷是因为你似乎误解了 functions
的工作原理
return Promise.map(nameList, function(personName){ <-- this function
for (var j=1; j<=10; j++){
return promises.push(new Promise(function(resolve, reject) { <-- is returning HERE
此处Array.prototype.push
函数返回新添加项的index
。 (我查了一下,直到)
这里最大的问题是你返回它。
一旦你 return
Promise.map
的 mapper
函数,你就告诉它你完成了!所以在你上面的代码中,它甚至不会进入 for loop
在 MDN 中查找规范以了解 return
它的说法
The return statement ends function execution and specifies a value to be returned to the function caller.
希望这能回答您提早返回的问题。
第二:我不会指望你的承诺
我自己也很难兑现承诺。让我引导您阅读我最近阅读的 awesome articles on promises。现在让我应用我从中学到的东西。谢谢你的提问。
我们承诺要兑现callback hell,但你却歪曲了所有承诺。
我会尝试从最嵌套的部分开始压平 promise
SOME_SEARCH_FX_THAT_RETURNS_A_PROMISE(params).then(function(data){
return Promise.map(data, function(item, index){
if (!_.has(jsonDict, item.key)){
jsonDict[item.key] = {
name: personName
}
}
return
}).then(function(){
console.log(jsonDict)
return resolve(true)
})
}).catch(function(err){
console.log(err)
return reject(false)
})
此处的内部承诺映射是不必要的,您甚至可以对 for loop
使用标准 map
,因为您实际上并未在此处映射任何内容...
[重构 1]
// Create subroutine, careful with the globals...
let populateJsonDict = singleData => {
if (!_.has(jsonDict, singleData.key)) jsonDict[singleData.key] = { name: personName }
}
SOME_SEARCH_FX_THAT_RETURNS_A_PROMISE(params).then(data => {
data.forEach(populateJsonDict);
resolve(true); // this will be removed later
}).catch(function(err){
console.log(err);
reject(false); // this will be removed later
})
好吧,让我们向上移动回调金字塔(或向下移动?)。下一个
for (var j=1; j<=10; j++){
return promises.push(new Promise(function(resolve, reject) {
params['page'] = j;
console.log('PAGE ' + j + ' ' + personName)
//[Refactored 1]
}))
}
这里又是一个不必要的 Promise,是时候摆脱它了。而这里问题的基石,return
[重构 2]
for (var j=1; j<=10; j++){
//[from Refactored 1]
let populateJsonDict = singleData => {
if (!_.has(jsonDict, singleData.key)) jsonDict[singleData.key] = { name: personName }
}
params['page'] = j; // I assume this a global somewhere
let p = SOME_SEARCH_FX_THAT_RETURNS_A_PROMISE(params).then(data => {
data.forEach(populateJsonDict);
// Removed because we've removed the parent promise
}).catch(function(err){
console.log(err);
// Removed because we've removed the parent promise
})
promises.push(p)
}
我会快进,因为我注意到这真的很长。下一个要重构的部分
return new Promise((res, rej) => {
var promises = [];
return Promise.map(nameList, function(personName){
//[Refactored 2]
}).then(function(){
return res(true)
})
}).then(function(){
console.log('Done with everything.')
})
我真的不知道如何挽救这个,所以我会从小组开始写东西。
[重构 3:final]
var promises = [];
nameList.forEach(personName => { // Like earlier, redundant Promise.map
//[from Refactored 2]
for (var j=1; j<=10; j++){
let populateJsonDict = singleData => {
if (!_.has(jsonDict, singleData.key)) jsonDict[singleData.key] = { name: personName }
}
params['page'] = j;
let p = SOME_SEARCH_FX_THAT_RETURNS_A_PROMISE(params).then(data => {
data.forEach(populateJsonDict);
}).catch(function(err){
console.log(err);
})
promises.push(p)
}
});
// At this point you have an array of Promises, for this we can utilize Promise.all
Promise.all(promises)
.then(() => console.log('Done with Everything'));
我想这本可以做得更好。让我做最后一个版本。
[重构 3.1:final]
let populateJsonDict = name => key => !_.has(jsonDict, key) && Object.assign(jsonDict, {[key]:name};
let promises = _.times(10,
index => {
params['page'] = index+1;
return Promise.map(nameList, name => {
let populateWithName = populateJsonDict(name);
let iterate = data => data.forEach(populateWithName);
return SOME_SEARCH_FX_THAT_RETURNS_A_PROMISE(params)
.then(iterate)
.catch(err => console.log(err));
});
});
Promise.all(promises)
.then(() => console.log('Everything done'));
好吧,仍然有这种不满意的感觉,但这就是我现在所拥有的......这对我来说真的比你更重要。所以再次感谢你的朋友。我希望我们都能继续推进这个不断变化的工作领域。抱歉,如果这一切听起来都居高临下。干杯!