嵌套 For 循环转换为嵌套 Promise

2023-12-20

我遇到了一个问题,我的程序仅在一次迭代时结束nameList,而且我不太确定不合逻辑的代码在哪里。

全局给出:

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

我复杂的嵌套从这里开始,但我不知道如何修复它,以便它迭代nameList和数字 for 循环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,我要提前回来,但似乎不知道在哪里。任何有关问题所在(甚至重构)的帮助/指导将不胜感激。提前致谢!


第一:你的代码从根本上来说是有缺陷的

为什么我说根本上有缺陷是因为你似乎误解了如何functions work

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

Here Array.prototype.push函数返回index新添加的项目。 (我查了一下,直到)
这里最大的问题是你回归 it.

只要你return the mapper的函数Promise.map http://bluebirdjs.com/docs/api/promise.map.html你告诉它你完成了!所以在上面的代码中,它甚至不会进入下一次迭代for loop

在 MDN 中查找规范return https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/return它说

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

希望这能回答您关于提前返回哪里的问题。


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

我自己也很难兑现诺言。让我引导您前往关于承诺的精彩文章 https://pouchdb.com/2015/05/18/we-have-a-problem-with-promises.html我最近读过。现在让我应用我从中学到的东西。谢谢你提出这个问题。

我们要兑现的承诺回调地狱 http://callbackhell.com/但你却把它的用途全部串起来了。

我会尝试从最嵌套的部分开始压平承诺

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

这里的内部承诺图是不必要的,你可以只使用标准map即使是一个for loop因为你实际上并没有在这里映射任何东西......

[重构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]
  }))
}

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

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

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

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

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

嵌套 For 循环转换为嵌套 Promise 的相关文章

随机推荐

  • d3.js 3D 数组插值

    代码在这里 http jsfiddle net S48QX http jsfiddle net S48QX 我想根据3D数据集绘制图像 例如 var data x 1 428 y 0 500 energy 0 458 x 1 428 y 1
  • 本地主机错误

    我在index php中有代码 在 head php 中
  • Mono 没有从我的 app.config 读取值?

    我有一个标准app config对于在项目 设置 选项卡中添加设置时由 Visual Studio 2010 创建的 NET 4 0 控制台应用程序 如 MSDN 上所述 应用程序设置 http msdn microsoft com en
  • 当 Openshift 说“驱逐”我的 pod 时,这是什么意思 - 为什么它一直这样做?

    我正在使用 OpenShift 3 StarterOpenShift 在线 http www openshift com运行一个小型网络项目 过去两个月一直运行良好 昨天突然停止运行 我发现部署只是陷入了 创建容器 当我尝试重建并重新启动项
  • 使 PowerShell 脚本在全局范围内运行 cmdlet

    我编写了以下 PowerShell 脚本 function Reload Module string moduleName module Get Module moduleName Remove Module moduleName Erro
  • 如何将鼠标光标从用户代码中移出?

    我的数据来自arduino 它从传感器获取数据 我想让用户程序处理数据 从 dev ttyUSB0 读取数据后 之后我需要使用程序的输出来控制鼠标光标 我真的很想避免此时编写内核驱动程序 推荐的方法是什么 在 Linux 环境中 也许是 X
  • 在 IE7 或 IE8 中查看打印 CSS

    我正在调试一个在打印时出现元素定位问题的网站 我有一个单独的 print css 文件 由具有 media print 属性的链接元素链接 此问题仅出现在IE7和IE8中 我正在寻找一种使用打印媒体类型查看页面的方法 但同时仍然可以使用 I
  • 将枚举与 Code First 和 Entity Framework 5 结合使用

    只是想确认一个印象 似乎 EF5 Code First 中的枚举仅在与使用它们作为属性类型的类在同一命名空间中声明时才受支持 谁能证实这一点吗 在网上找不到任何与此相关的内容 之前修复的相关错误 4 3 Beta 1 发行说明说 错误修复G
  • 将datagridView保存到sql数据库中

    第一次将数据网格保存到数据库 感谢您的帮助 我这样填充dataGrid private void FillGrid1 frmEditovat frm2 new frmEditovat this DataTable DT null DataR
  • 在DBeaver中查看主键

    DBeaver中有没有快速查看表主键的方法 就像例如在 Eclipse 数据源资源管理器中 其中主键行标有 PK 和特殊符号 对于给定的表 右键单击表名 在数据库导航器中 gt 选择查看图表 This will open a window
  • Excel VBA 尝试使用 For 循环将“MAX”公式写入具有不同范围的单元格

    我试图让 VBA 将公式写入不同的单元格 该公式将找到由某些变量决定的范围的最大值 我的变量I and J是 数字 整数 这是我的代码 Sub AddMAX Dim I As Integer Dim J As Integer Dim L A
  • Java:长格式的 util.Date 对象

    如何返回具有长值的 Date 对象 就像是 JsonProperty time public Date getTimeInLong Date date super getTime return date getTime I want thi
  • 运行 Apache 时,Django 打开 SQLite3 db 文件时出错

    我收到这个错误 操作错误 无法打开数据库文件 到目前为止我尝试过的事情是在 settings py 中设置 dev db 文件的绝对路径 我尝试将 www data 添加到我的管理组 并将项目文件夹的组设置为 admin 并将该组设置为 w
  • 将字符串列表从 Python 传递到 Rust

    我已经学习 Rust 大约两周了 今天 我进入了它的 FFI 我使用 Python 来玩 Rust 使用 ctypes 和 libc 我传递了整数 字符串 甚至学会了传递整数列表 感谢这个精彩的答案 https stackoverflow
  • Sqlite 与基于文件的数据存储?

    假设我有一个类似的课程 如下所示 class User attr accessor name age def initialize name age name age name age end end 现在 将用户保存为单个文件中 User
  • 是否可以通过单击链接/按钮来运行 php artisan 命令

    所以正如问题所说 当用户单击网络浏览器中的链接时 有没有办法在后台运行 php artisan 命令 例如 我想在我的应用程序中创建一个用于迁移迁移文件的按钮 因此当单击此按钮时 a href migrate class btn btn p
  • android 绑定到 AccessibilityService

    我创建了一个android服务 它是AccessibilityService 根据我的活动 我想绑定到该服务 没有进程间通信 所以我尝试创建一个本地Binder仅返回服务的实现 如本例所示http developer android com
  • 在webapp中获取当前的svn版本

    在 java web 应用程序中显示 使用修订号的最佳方式是什么 我们只使用 ant 来构建我们的 war 存档 没有构建服务器之类的 我希望有某种 if ref 可以写入资源文件中 但这仅在提交相关文件时更新 我在全球范围内都需要它 你会
  • 如何搜索包含 JSON 数组的 SQL 列

    我有一个包含单个 JSON 数组的 SQL 列 names Joe Fred Sue 给定一个搜索字符串 如何使用 SQL 在名称数组中搜索匹配项 我正在使用 SQL 2016 并查看了 JSON QUERY 但不知道如何在 JSON 数组
  • 嵌套 For 循环转换为嵌套 Promise

    我遇到了一个问题 我的程序仅在一次迭代时结束nameList 而且我不太确定不合逻辑的代码在哪里 全局给出 var require underscore var nameList Bob Susie var jsonDict 我复杂的嵌套从