如何通过嵌套正确链接 Promise

2024-04-17

我的节点项目当前包含嵌套回调的侧向圣诞树,以便获取数据并按正确的顺序处理它们。现在我正在尝试使用 Promises 重构它,但我不确定如何正确执行。

假设我要获取办公室列表,然后获取每个办公室的所有员工,然后获取每个员工的工资。最后,所有实体(办公室、员工和工资)都应该链接在一起并存储在数据库中。

一些伪代码说明了我当前的代码(省略了错误处理):

fetch(officesEndpoint, function (data, response) {
    parse(data, function (err, offices) {
        offices.forEach(function (office) {
            save(office);
            fetch(employeesEndPoint, function (data, response) {
                parse(data, function (err, employees) {
                    // link each employee to office
                    save(office);
                    save(employee);
                    employees.forEach(function () {
                        fetch(salaryEndpoint, function (data, response) {
                            parse(data, function (err, salaries) {
                                // link salary to employee
                                save(employee);
                            });
                        });
                    });
                });
            });
        });
    });
});

我尝试用承诺来解决这个问题,但有几个问题:

  • 有点冗长?
  • 每个办公室都需要与其各自的员工联系起来,但在saveEmployees功能我只能访问员工,而不能访问链中更上层的办公室:

var restClient = require('node-rest-client');
var client = new restClient.Client();
var xml2js = require('xml2js');

// some imaginary endpoints
var officesEndpoint = 'http://api/offices';
var employeesEndpoint = 'http://api/offices/employees';
var salaryEndpoint = 'http://api/employees/:id/salary';


function fetch (url) {
    return new Promise(function (resolve, reject) {
        client.get(url, function (data, response) {
            if (response.statusCode !== 200) {
                reject(statusCode);
            }
            resolve(data);
        });
    });
}

function parse (data) {
    return new Promise(function (resolve, reject) {
        xml2js.parseString(data, function (err, result) {
            if (err) {
                reject(err);
            }
            resolve(result);
        });
    });
}

function saveOffices (offices) {
    var saveOffice = function (office) {
        return new Promise(function (resolve, reject) {
            setTimeout(function () {  // simulating async save()
                console.log('saved office in mongodb');
                resolve(office);
            }, 500);
        })
    }
    return Promise.all(offices.map(saveOffice));
}

function saveEmployees (employees) {
    var saveEmployee = function (employee) {
        return new Promise(function (resolve, reject) {
            setTimeout(function () { // simulating async save()
                console.log('saved employee in mongodb');
                resolve(office);
            }, 500);
        })
    }
    return Promise.all(offices.map(saveEmployee));
}

fetch(officesEndpoint)
.then(parse)
.then(saveOffices)
.then(function (savedOffices) {
    console.log('all offices saved!', savedOffices);
    return savedOffices;
})
.then(function (savedOffices) {
    fetch(employeesEndPoint)
    .then(parse)
    .then(saveEmployees)
    .then(function (savedEmployees) {
        // repeat the chain for fetching salaries?
    })
})
.catch(function (error) {
    console.log('something went wrong:', error);
});

您不一定必须嵌套,这也可以:

fetch(officesEndpoint)
  .then(parse)
  .then(saveOffices)
  .then(function(savedOffices) {
    console.log('all offices saved!', savedOffices);
    return savedOffices;
  })
  .then(function(savedOffices) {
    // return a promise
    return fetch(employeesEndPoint); // the returned promise can be more complex, like a Promise.all of fetchEmployeesOfThisOffice(officeId)
  })
  // so you can chain at this level
  .then(parse)
  .then(saveEmployees)
  .then(function(savedEmployees) {
    return fetch(salariesEndPoint);
  })
  .catch(function(error) {
    console.log('something went wrong:', error);
  });
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何通过嵌套正确链接 Promise 的相关文章

  • 如何在 AngularJS 中读取 Java 属性文件?

    有什么方法可以从位于网络服务器外部的 angularjs 读取属性文件吗 就像在java中一样 属性文件部署在项目之外 但是我们可以将项目中的这些文件作为filter properties读取 这样任何解决方案都可以在AngularJS中找
  • Javascript正则表达式替换多个组

    我正在尝试根据这样的正则表达式替换多个匹配的组 var paramRegex s w s w s w s s i should match group1 group2 group3 var emptyParam emptyParam rep
  • 如何取消js文件的压缩?

    如何取消通过 webpack 工具缩小的 js 文件 缩小之前 function autoslideSlider next slide trigger click window on load function preloader fade
  • Edge 中的 Javascript 仅适用于打开的 devtools

    我遇到的问题是 在 MS Edge 中 我的图像映射功能只能部分工作 它由淘汰赛 FW 提供动力 在更大的图像映射上 它不会将整个图像映射注册到视图模型中 因此 图像映射的所有悬停效果和单击样式都会停止工作 然而 这只是大图像地图的问题 还
  • React Native:使用 Linking api 设置标头

    如何在 React Native 中设置RequestHeader 就像下面这样 var client new XMLHttpRequest client open GET http www example com api client s
  • path.join 与 path.resolve 与 __dirname

    使用时有区别吗both path join and path resolve with dirname用于解析 Node js 中的绝对路径 像这样使用时应该首选其中之一 绝对路径分辨率占用例的 90 I e const absoluteP
  • Internet Explorer 无法打开 Internet 站点操作中止,如何修复此错误?

    此代码在 IE 中给出错误 Internet Explorer 无法打开 Internet 站点操作中止 如何修复此错误 var tip p Most computers will open PDF documents tip automa
  • d3.js:在树布局中展开多个路径

    My JSON contains same node names in different paths I would like to be able to open all children with the same name or h
  • 覆盖骨干模型更改事件

    我认为我想做的事情很简单 我只是不知道该怎么做 当我的模型属性之一发生更改以便将一些数据传递给事件处理程序时 无论更改是值的增加还是减少 我想触发我自己的事件 基本上我希望我的处理程序在视图中执行此操作 handler function i
  • div 中的内部 html 更改时触发事件

    I have div对于一些信息 填写为 innerHTML单击按钮 目标是我想要 slideDown添加 div 中的文本时的 div 可以用 jQuery 来实现吗 Example div div 将文本添加到 div document
  • 如何通过向上移动到地址栏来检测鼠标离开页面?

    我创建了一个 jQuery 事件 当访问者离开页面时会弹出一个对话框 我正在使用 e pageY 来检测鼠标位置 当鼠标位于Y 小于2时 弹出对话框 问题是 当我向下滚动页面并决定离开页面时 弹出窗口不会显示 因为鼠标不在 Y 小于 2 处
  • jquery 改变标签

    我的代码不起作用 你能帮我吗 我希望将 class s7 的标签名称 p 更改为 h1 问题是您将所有元素与类相匹配s7 但是您需要对它们进行一一处理 以便将其内容复制到新元素中 在您当前的代码中 this总是document 不是当前元素
  • Angular 2 - 通过引用传递对象字段。可重复使用的编辑对象的方式

    我正在创建可重用的表组件 该组件将允许编辑对象字段 以准备将它们发送到 API 拥有一个对象 person name John job type IT title Software Engineer 我想将对象嵌套字段传递给组件并进行编辑
  • 在 Javascript 构造函数中引用实例变量

    我试图通过执行以下操作来维护对象的状态 obj function this foo undefined this changeState function function this foo bar This is contrived bu
  • javascript - 如何防止 toFixed 对小数进行四舍五入

    我对 html javascript 和 css 很陌生 所以如果我的问题对你来说听起来很愚蠢 请原谅 我的问题是如何阻止该功能toFixed 来自小数的四舍五入 这是我的链接 http jsfiddle net RWBaA 4 http
  • 加载对象内容后运行 Javascript 函数

    当内容的内容时 如何运行 Javascript 函数已加载 这DOMContentLoaded事件在此之前触发 以及依赖它的东西 例如 JQuery 的 同样地 Compare this http plnkr co edit znu5iz3
  • AngularJS 和 Webpack 集成

    我正在寻找一些使用帮助webpack http webpack github io docs 对于大型 AngularJS 应用程序 我们使用基于功能的文件夹结构 每个功能 页面都有一个模块 并且它们有控制器 指令 我已经成功配置了 web
  • 在 Windows 7 中安装 Express.JS 的问题

    我已通过其网页上的安装程序安装了 Node js 并将其路径添加到我的环境变量中 以便我可以使用node and npm通过命令行 如果我制作一个快速应用程序 它可以工作 但我必须手动创建它 我想这很好 但我想知道为什么我不能使用expre
  • javascript 在提示后显示用户输入

    我想在用户完成信息输入后显示用户输入的内容 当用户到达最后一个提示时 我希望页面显示他们输入的内容 例如 如果他们在名称部分下输入 apples 我希望它在底部代码的 P1 部分中列出单词 apples 我是 javascript 的新手
  • 量角器元素(..)从单独的文件返回未定义

    我正在编写一个 Protractor 测试 在我的 test step js 文件中我有 element by css getText then function text expect text to equal expectedText

随机推荐

  • Protractor 中的全局 beforeEach 和 afterEach

    在每个规范中我都有beforeEach and afterEach声明 是否可以以某种方式全局添加它以避免规范之间的代码重复 目的beforeEach and afterEach 函数是添加一个重复代码块 每次开始或完成执行每个规范时都需要
  • HTML5 Canvas:绘制完成时获取事件

    我正在将图像绘制到画布元素 然后我就有了依赖于这个过程来完成的代码 我的代码如下所示 var myContext myCanvasElement getContext 2d myImg new Image myImg onload func
  • 什么是位掩码?

    我对 C 编程相当陌生 并且遇到了位掩码 位掩码的一般概念和作用是什么 非常感谢例子 掩码定义要保留哪些位以及要清除哪些位 屏蔽是将屏蔽应用于值的行为 这是通过执行以下操作来完成的 按位与运算以提取值中的位子集 按位或运算以设置值中的位子集
  • 大数据请求体为空

    我在 post 方法的正文中发送大量文本 我使用 Postman 来测试这一点 但是它工作正常 我可以像这样读取请求正文 String text request body asText 但是当我尝试在正文中发送大量数据时 我得到的文本为空
  • Websphere 7集群部署

    我们有一个 J2EE 应用程序作为 EAR 文件 部署在 WAS 7 中 为了使应用程序可用性尽可能高 需要部署在 3 个集群中 我们有一个 Quartz Scheduler 类 其工作是每天凌晨 2 00 将数据从一个数据库上传到另一个数
  • MobX-State-Tree 流程中的类型化 Yield 表达式

    在 MobX state tree MST 中执行异步操作的推荐方法是使用flow https mobx state tree js org concepts async actions 它接受一个生成器函数作为第一个参数 其中每个承诺都应
  • 在 Docker 容器接口上应用 NetEM WAN 延迟

    我想对 docker 容器的出口流量应用 NetEm 延迟 通常 我运行 sbin tc qdisc add dev INTERFACE root netem delay DELAY ms 问题是我不知道容器连接到的接口 例如 我正在运行以
  • 本地化 JavaAnpr 以获取本地车牌

    我正在与JavaAnpr http javaanpr sourceforge net 自动识别车牌 虽然它适用于欧洲车牌 但不适用于我的国家 例如 如何编辑资源文件和语法 XML 以支持其他国家 地区 michel layyous 这是作者
  • 从二元高斯分布生成均值

    我正在阅读统计学习要素ESLII http www stat stanford edu tibs ElemStatLearn 在第二章中 他们用高斯混合数据集来说明一些学习算法 为了生成该数据集 他们首先从二元高斯分布 N 1 0 I 生成
  • 如何在 Windows PowerShell 中使用 .bat 文件更改当前目录?

    我正在学习 Windows PowerShell 并且正在努力完成非常基本的任务 如何创建 bat 文件来更改当前目录 简单的 bat 文件cd mydir里面用得很好cmd exe 但它在 PowerShell 中不起作用 PS C Us
  • 将条目插入到 crontab 中,除非它已经存在(如果可能的话作为单行)[重复]

    这个问题在这里已经有答案了 将条目插入 etc crontab 的首选方法是什么 除非它存在 最好使用单行 这是我希望放入 etc crontab 中的示例条目 除非它已经存在于其中 1 some user python mount sha
  • 在 .NET core 2.0 中创建迁移步骤时,将“IDesignTimeDbContextFactory”的实现添加到项目错误中

    我有一个 NET core 1 0 web 应用程序运行良好 我必须升级到 NET Core 2 0 我还必须为我的 SQLite 数据库添加迁移步骤 如果我启动这个命令 添加迁移 MyMigrationStepName 我收到此错误 无法
  • JMS 会话寿命长。保持 JMS 连接/JMS 会话总是打开是一种不好的做法吗?

    保持 JMS 连接 会话 消费者始终打开是一种不好的做法吗 代码草案示例 app startup code ConnectionFactory cf ConnectionFactory jndiContext lookup CF JNDI
  • 将 GCC 内联汇编与采用立即值的指令结合使用

    问题 我正在为 ARM Cortex M3 处理器开发定制操作系统 为了与我的内核交互 用户线程必须生成 SuperVisor Call SVC 指令 以前称为 SWI 用于软件中断 该指令在ARM ARM中的定义是 这意味着该指令需要即时
  • itextsharp 不关闭文件

    我有一些用于 itextsharp 合并 2 个 pdf 文件的代码 在网上某处找到的 合并工作正常 但似乎源文件在全部完成后仍在使用 我想做的是删除我已经合并的第一个文件 通过文件上传上传 并仅保留合并的文件 肯定是执行合并的代码导致文件
  • AWS 上的 Laravel 调度任务无法正常工作

    我正在将 Laravel 应用程序部署到 ElasticBeanstalk 环境 我正在尝试在服务器上的计划任务中运行命令 但它不起作用 这就是我所做的 我在 Kernel php 文件中安排命令如下 schedule gt command
  • Solaris C++ 流输入 >> 运算符和模板的模板

    我有一个编译器选项 我可以在 CC 编译器中使用它来获取以下代码 在 Visual C 中编译良好 std vector
  • Android 和 Java 中的 RSA 加密

    我想用 RSA 加密来加密字符串 我的公钥 私钥已生成并存储在数据库中 在android中 我使用这段代码 public static String encryptRSAToString String text String strPubl
  • 如何在R中识别坐标

    我想确定向量的哪个坐标给我带来最大的价值 举一个简单的例子 假设 x lt c 10 22 20 18 5 最大值是22 但是如何自动识别坐标2具有最大值呢 Thanks which max正如 Hong Ooi 指出的那样 是你的朋友 g
  • 如何通过嵌套正确链接 Promise

    我的节点项目当前包含嵌套回调的侧向圣诞树 以便获取数据并按正确的顺序处理它们 现在我正在尝试使用 Promises 重构它 但我不确定如何正确执行 假设我要获取办公室列表 然后获取每个办公室的所有员工 然后获取每个员工的工资 最后 所有实体