嵌套For循环转换为嵌套Promise [英] Nested For Loops converted to Nested Promises

查看:80
本文介绍了嵌套For循环转换为嵌套Promise的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我遇到了一个问题,我的程序只在 nameList 的一次迭代中结束,我不确定这个不合逻辑的代码在哪里。

I'm running into a problem where my program ends only on one iteration of the nameList, and I'm not exactly sure where the illogical code lies.

给定全球:

var _ = require("underscore");
var nameList = ["Bob", "Susie"]
var jsonDict = {}

我的复杂嵌套从这里开始,但我不知道如何修复它以便它遍历 nameList 和-循环<$ c的数字$ c> 1-10 :

My complicated nesting starts here, but I'm not sure how to fix it so that it iterates through both the nameList and the numbers 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 的数据,我早点回来,但似乎无法弄清楚在哪里。任何有关问题所在的帮助/指导(甚至是重构)都将受到赞赏。提前致谢!

and I never get the data for Susie, I'm returning early but can't seem to figure out where. Any help/guidance in where the problem lies (or even refactoring) would be appreciated. Thanks in advance!

推荐答案

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



为什么我说基本上有缺陷是因为你似乎误解了函数如何工作

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 function返回新添加项目的 index 。(我查了一下,TIL)

这里最大的问题是你退回它。

Here Array.prototype.push functionreturns the index of the newly add item. (I looked it up,TIL)
The biggest issue here is that you are RETURNING it.

一旦你返回 <的 mapper 功能code> Promise.map 你告诉它你完成了!所以在你上面的代码中,它甚至不会到达下一个它循环的循环

As soon as you return the mapper function of Promise.map you're telling it that your done! So in your code above, it wouldn't even get to the next iteration of the for loop

在MDN中查找 返回 表示

Look up specifications in MDN for return its says


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

The return statement ends function execution and specifies a value to be returned to the function caller.

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

Hopefully this answer your question to where you are returning early.

我也很难度过许诺。让我指导你一个关于承诺的精彩文章我最近读过。现在让我运用我从中学到的东西。感谢您提出这个问题。

I too had myself a difficult time grokking promises. Let me direct you to an awesome articles on promises I recently read. Now let me apply what I learned from that. Thank you for this question.

承诺我们打击回调地狱但是你把所有的东西都串起来了。

Promises we're made to combat callback hell but you skewered all that it was made for.

我会尝试从最嵌套的作品中展平承诺

I'll try to flatten the promises starting from the most nested piece

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循环,因为你实际上并没有在这里映射任何东西...

The inner promise map here is unnecessary, you could just use a standard map for even a for loop since you're not actually mapping anything here...

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

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

Okay let's move up the callback pyramid (or move down?). Next on the list

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

这里又是另一个不必要的承诺,是时候摆脱它了。这个问题的基石,返回

Again another unnecessary Promise here, time to get rid of that. And that cornerstone of the issue here, the 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)
}

我会快速前进,因为我注意到了这变得非常漫长。重构的下一部分

I'll fastforward as i noticed this is getting really long. Next piece to refactor

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

我真的不知道如何挽救这个,所以我会从小组写东西。

I don't really know how to salvage this so I'll write things from group up.

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

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

I suppose that could have been done better. Let me do one last version of this.

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

好吧,仍然有这种不满意的感觉,但这就是我现在所拥有的......这对我来说真的比你更多。所以再次感谢你的朋友。我希望我们两个都能继续前进,这是一个不断变化的工作领域。如果这一切听起来无论如何都道歉。干杯!

Okay, still have this felling of un-satisfaction but that's what I have for now... That was really more for me than you. So thank you again friend. I hope we both can continue to advance is this ever changing field of work. Apologies if all this sounds condescending in anyway. Cheers!

这篇关于嵌套For循环转换为嵌套Promise的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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