嵌套 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 的相关文章

  • 将鼠标悬停时的鼠标光标更改为锚状样式

    如果我将鼠标悬停在div鼠标光标将更改为 HTML 锚点中的光标 我怎样才能做到这一点 假设你的div has an id myDiv 将以下内容添加到您的 CSS 中 这cursor pointer指定光标应与用于锚点 超链接 的手形图标
  • Javascript Promise“then”始终运行,即使 Promise 未能执行

    我希望当调用第二个 then 时不执行第三个 then 但是 即使 Promise 被拒绝 调用第二个 then 并且代码返回 rejected 然后返回 undefined 它仍然调用第三个 then 如何不运行第三个 then 这样 未
  • 为什么 iife 在一个简单的例子中不起作用?

    我不明白为什么函数表达式调用不起作用并抛出错误 你能给我解释一下吗 var a function x alert x function a 1 谢谢大家 任务比我想象的要容易得多 这是因为 JS 将 IIFE 解析为函数的参数调用 这样做时
  • IE从哪个版本开始支持Object.create(null)?

    您可以通过多种方式在 JavaScript 中创建对象 creates an object which makes the Object prototype of data var data1 new Object Object liter
  • Chrome 中的性能问题

    我目前正在从事一个相对较大的项目 使用 AngularJs 构建 应用程序的一部分是一个表单 您可以向其中添加任意数量的页面 不幸的是 添加了很多不必要的垃圾 即表示表单模型的对象可能会变得非常大 在某些时候 Chrome 基本上无法处理它
  • 如何使用javascript将大图像转换为十六进制?

    如果我尝试将图像转换为十六进制 无论我使用哪个函数 我都会收到此错误消息 该图像的大小为 7 MB 19812 毫秒 清理 1401 2 1455 0 gt 1401 2 1455 0 MB 9 9 0 ms 自上次 GC 以来 8 3 m
  • 摩卡 - Chai Karma“套件未定义”

    我对 jscript tdd 很陌生 遇到了问题 希望有人能告诉我我在做什么 在浏览器中运行测试 通过 HTML 文件 一切正常 通过节点和业力运行它们我得到以下异常 我想在 node js 主机的 karma 中使用 Mocha 和 Ch
  • 如何针对 Node.js 中发生的每个错误发送电子邮件?

    假设我的 node js 应用程序正在运行 如果出现错误 我的意思是所有错误 不仅仅是网络错误 如果出现错误 则很重要 我如何调用函数向我发送电子邮件 基本上 在我希望它写入 err out 之前 我希望向我发送一封电子邮件 我正在使用no
  • 可以在初始 DOM 解析期间/之前修改 DOM 吗?

    是否可以在初始 DOM 解析期间或之前修改 DOM 或者我是否必须等到 DOM 被解析和构建之后才能与其交互 更具体地说 是否有可能阻止 DOM 中的脚本元素使用用户脚本 内容脚本或 Chrome 或 Firefox 中的类似脚本运行 在解
  • Bootstrap按钮加载+Ajax

    我正在使用 Twitter Bootstrap 的按钮加载状态 http twitter github com bootstrap javascript html buttons http twitter github com bootst
  • 有没有办法使用 Rspec/Capybara/Selenium 将 javascript console.errors 打印到终端?

    当我运行 rspec 时 是否可以让 capybara selenium 向 rspec 报告任何 javascript console errors 和其他异常 我有一大堆测试失败 但当我手动测试它时 我的应用程序正在运行 如果不知道仅在
  • 设置 cookie 时中断 JavaScript 执行

    当设置 cookie 时 是否可以始终中断浏览器开发人员工具中的 javascript 执行 无需显式设置 JS 断点 document cookie 在 html head 块的开头添加此代码片段效果很好
  • 尝试将数据存储在点击器网站中

    我正在尝试存储一个名为的变量score无论何时刷新 您都会一次又一次地使用它 我不明白的是它的代码是什么 我尝试了一些方法 但似乎都不起作用 这是我的答题器网站 但是当我尝试使用 JavaScript 来存储它时 它不起作用window o
  • Vuejs 2:去抖动不适用于手表选项

    当我在 VueJs 中反跳此函数时 如果我提供毫秒数作为原语 它就可以正常工作 但是 如果我将其提供为对 prop 的引用 它会忽略它 这是道具的缩写版本 props debounce type Number default 500 这是不
  • 从数据库检查数据的异步解决方案各种循环子句

    我想要做的是异步检查数据库并从中获取结果 在我的应用程序中我试图实现Asynchronously将此步骤解决为 从数据库中检查手机号码JsonArray循环子句的种类 Create JsonArray从结果 打印创建的数组 我学到了足够多的
  • Three.js 各种大小的粒子

    我是 Three js 的新手 正在尝试找出添加 1000 个粒子的最佳方法 每个粒子都有不同的大小和颜色 每个粒子的纹理是通过绘制画布创建的 通过使用粒子系统 所有粒子都具有相同的颜色和大小 为每个粒子创建一个粒子系统是非常低效的 有没有
  • Vue 和 Vuex:处理依赖的计算属性

    我的应用程序是一个使用 Vuex 在 Vue 中构建的精简电子表格 关键组件是TableCollection Table and Row The TableCollection有一个包含多个的数组Table对象 每个Table有一个包含多个
  • 在 JavaScript 循环之外声明变量可以提高速度和内存?

    C 也有类似的问题 但我们没有看到 JavaScript 的任何问题 在循环内声明变量是否可以接受 假设循环有 200 次迭代 使用样本 2 相对于样本 1 是否有性能要求 内存和速度 我们使用 jQuery 来循环 它提高了我们将 var
  • 如何用另一个响应替换窗口的 URL 哈希?

    我正在尝试使用替换方法更改哈希 URL document location hash 但它不起作用 function var anchor document location hash this returns me a string va
  • 如何确定所有角度2分量都已渲染?

    当所有 Angular2 组件完成渲染时 是否会触发一个角度事件 For jQuery 我们可以用 function 然而 对于 Angular2 当domready事件被触发 html 只包含角度组件标签 每个组件完成渲染后 domrea

随机推荐

  • 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 我复杂的嵌套从