嵌套For循环转换为嵌套Promise

时间:2017-03-17 08:56:28

标签: javascript promise bluebird

我遇到了一个问题,我的程序只在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的数据,我很早就回来了,但似乎无法弄清楚在哪里。任何有关问题所在的帮助/指导(甚至是重构)都将受到赞赏。提前谢谢!

1 个答案:

答案 0 :(得分:1)

首先:您的代码存在根本缺陷

为什么我说基本上有缺陷是因为你似乎误解了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。 (我查了一下,TIL)
这里最大的问题是你退回它。

只要您return mapper for loop {{}}}功能,您就会告诉您已完成!因此,在上面的代码中,它甚至无法进入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) }) 的下一次迭代

在MDN中查找Promise.map的说明

  

return语句结束函数执行并指定要返回给函数调用者的值。

希望这可以回答你提前返回的问题。

第二:我不会指望你的承诺

我也让自己陷入了承诺的困难时期。让我指导一下我最近阅读的return。现在让我运用我从中学到的东西。谢谢你提出这个问题。

承诺我们打击awesome articles on promises,但你把它所做的一切都串起来了。

我会尝试从最嵌套的作品

开始展平承诺
map

此处的内部承诺地图是不必要的,您甚至可以使用标准的for loop// 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 }) ,因为您实际上并未在此处映射任何内容......

[重构1]

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]
  }))
}

好吧让我们向上移动回调金字塔(或向下移动?)。列表中的下一步

return

这里又是另一个不必要的承诺,是时候摆脱它了。这个问题的基石,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) }

[重构2]

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.')
})

我快速前进,因为我注意到它变得非常长。下一篇重构

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:最终]

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'));

我认为可以做得更好。让我做最后一个版本。

[重构3.1:最终]

connection test
address test.mosquitto.org
topic oust_topicst_topic out 0
try_private false
notifications false
bridge_attempt_unsubscribe true

好吧,仍然有这种不满意的感觉,但这就是我现在所拥有的......这对我来说真的比你更重要。再次感谢你的朋友。我希望我们都能继续前进,这是一个不断变化的工作领域。抱歉,如果所有这些听起来都是居高临下的话。干杯!