首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >问答首页 >在Javascript中,通过一系列承诺传递状态的模式是什么?

在Javascript中,通过一系列承诺传递状态的模式是什么?
EN

Stack Overflow用户
提问于 2014-04-06 02:16:15
回答 2查看 1.5K关注 0票数 9

我正在尝试学习一些关于Node和异步编程的知识。我读到了有关承诺的文章,并尝试在一个小项目中使用它们,该项目将用户的帖子从服务A复制到服务B。我很难理解如何最好地在承诺之间传递状态。

该项目是使用NodeJS为允诺库编写的。

我目前问题的一个简单定义是:

  • 如果服务B中不存在用户的帖子,则将用户的帖子从服务A复制到服务B。
  • 这两个服务都提供了http API,需要一个不值得记忆的用户id来查找该用户的帖子,因此必须从用户名中查找用户id。
  • 所有的http调用都是异步的。

这是一些伪代码,说明了我是如何将承诺链接在一起的。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
Promise.from('service_A_username')
  .then(getServiceAUserIdForUsername)
  .then(getServiceAPostsForUserId)
  .then(function(serviceAPosts) {
    // but what? store globally for access later?
    doSomethingWith(serviceAPosts);
    return Promise.from('service_B_username');
  })
  .then(getServiceBUserIdForUsername)
  .then(getServiceBPostsForUserId)
  .done(function(serviceBPosts) {
    // how do we interact with Service A posts?
    doSomethingThatInvolvesServiceAPostsWith(serviceBPosts); 
  });

我想做几件事:

  1. 将getIdForUsername调用引入getPostsForUserId函数中。然而,我希望按照‘做一件事并做好它’的原则,使每个功能单元尽可能简单。
  2. 创建一个“上下文”对象,并将其传递到整个链中,读取并存储该对象中的状态。然而,,这种方法使每个函数都非常适合于一个链,因此很难单独使用。

还有其他选择吗?建议采用什么方法?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2014-04-06 02:37:17

我会用Promise.all,就像这样

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
Promise.all([Promise.from('usernameA'), Promise.from('usernameB')])
    .then(function(result) {
        return Promise.all([getUsername(result[0]),getUsername(result[1])])
    })
    .then(function(result) {
        return Promise.all([getPosts(result[0]),getPosts(result[1])]);
    })
    .then(function(result) {
        var postsA = result[0], postsB = result[1];
        // Work with both the posts here
    });
票数 3
EN

Stack Overflow用户

发布于 2014-04-06 05:35:29

首先是个好问题。这是我们(至少我)经常处理的事情。在我看来,这也是一个承诺真正超越了回调的地方。

这里所做的基本上是,你真正想要的是你的图书馆没有的两样东西:

  1. .spread,它接受返回数组并将其从数组参数更改为参数的承诺。这允许将像.then(result) { var postsA = result[0], postsB = result[1];这样的东西切割到.spread(postsA,postsB中。
  2. .map,它获取一个承诺数组,并将数组中的每个承诺映射到另一个承诺--它类似于.then,但对于数组的每个值。

有两个选项,要么使用已经像蓝鸟那样使用它们的实现,因为它比现在的替代方案(更快、更好的堆栈跟踪、更好的支持、更强大的特性集)要好得多,要么可以实现它们。

由于这是一个答案,而不是一个库推荐,所以让我们这样做:

让我们从扩展开始,这相对容易--这意味着调用Function#apply将数组扩展到varargs。下面是一个示例实现i 偷了我自己的东西:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
if (!Promise.prototype.spread) {
    Promise.prototype.spread = function (fn) {
        return this.then(function (args) {
         //this is always undefined in A+ complaint, but just in case
            return fn.apply(this, args); 
        });

    };
}

接下来,让我们来做映射。承诺上的.map基本上只是数组映射,然后:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
if(!Promise.prototype.map){
    Promise.prototype.map = function (mapper) {
        return this.then(function(arr){
             mapping = arr.map(mapper); // map each value
             return Promise.all(mapping); // wait for all mappings to complete
        });
    }
}

为了方便起见,我们可以引入静态的.map来启动链:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
Promise.map = function(arr,mapping){
     return Promise.resolve(arr).map(mapping);
};

现在,我们可以像实际想要的那样编写您的代码:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
var names = ["usernameA","usernameB"]; // can scale to arbitrarily long.
Promise.map(names, getUsername).map(getPosts).spread(function(postsA,postsB){
     // work with postsA,postsB and whatever
});

这就是我们一直想要的语法。没有代码重复,它枯燥,简洁,清晰,承诺的美。

请注意,这并没有触及蓝知更鸟所做的事情的表面--例如,蓝鸟会检测到它是一个地图链,并且在没有完成第一个请求的情况下将函数“推送”到第二个请求上,所以第一个用户的getUsername不会等待第二个用户,但是如果更快的话,实际上会调用getPosts,所以在这种情况下,它与您自己的gist版本一样快,而imo更清晰。

然而,它是有效的,是不错的。

简单的A+实现更适合于承诺库之间的互操作性,并且应该是一个“基线”。在设计特定平台时,它们是有用的--小APIs - IMO几乎从来没有。像蓝鸟这样的可靠库可以显着地减少代码。您正在使用的承诺库,甚至在它们的文档中都这样说:

它的设计是为了使基础点正确,这样您就可以在其之上构建扩展的承诺实现。

票数 6
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/22892681

复制
相关文章
Mongodb只读副本集如何切换到读写模式
Mongodb副本集具备自动故障转移的高可用特性,通常所说副本集是1主2从的架构,当主节点出现故障时,剩下2个节点会自动进行选出新主节点,提供对外服务.也可以进行主动维护,将主节点降级为从节点,将从节点提升为主节点.本次要介绍是当副本集中只有1个节点活着,其他节点全部异常,此时仅存的节点自动变成secondary,只能提供只读业务,无法提供写入业务.只有secondary变成primary才可以写入,此时应该如何做?
徐靖
2020/08/13
2.2K0
03: 打开摄像头
学习打开摄像头捕获照片、播放本地视频、录制视频等。图片/视频等可到文末引用处下载。
CodecWang
2021/12/07
1.9K0
Mongodb只读副本集如何切换到读写模式(下)
接上一篇文章《Mongodb只读副本集如何切换到读写模式》,大概思想就是如何强制把副本集中仅存secondary节点提升为主,主要是通过standalone方式重启实例来实现,经过与大家交流与沟通,虽然此方式可以实现,但是以前老节点必须重新初始化,尤其当单节点数据很大时,此方式是缺点明显.最有效方式是通过rs.reconfig()方式来实现.此方式也分为2种:
徐靖
2020/08/13
1.4K0
ubuntu打开usb摄像头
1、保持在 ubuntu 界面,插上 usb 摄像头,将 usb 摄像头连接到虚拟机上。
Gnep@97
2023/08/10
1.9K0
ubuntu打开usb摄像头
利用python打开别人手机摄像头_python 摄像头
发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/169904.html原文链接:https://javaforall.cn
全栈程序员站长
2022/09/22
2.6K0
利用python打开别人手机摄像头_python 摄像头
opencv之打开摄像头、边缘检测
许多工业相机或某些视频I / O设备不为操作系统提供标准的驱动程序接口。因此,您不能在这些设备上使用VideoCapture或VideoWriter。
全栈程序员站长
2022/07/23
3.4K0
opencv之打开摄像头、边缘检测
Android App java 读取raw图像数据然后显示
src\main\java\com\wfh\canvasdemo\DataUtil.java
IT工作者
2022/05/20
6630
如何从Windows切换到Linux
微软已经马上准备在2020年1月份终止对Windows 7的支持,这意味着您将不再获得bug修复或安全更新。如果您是Windows 7的最终支持者之一,并且不想陷入一个不安全的系统,则可以选择:升级到Windows 10或完全切换到其他版本。
用户6543014
2020/02/10
3.9K0
小米手机_如何打开开发者模式?[通俗易懂]
大多数手机的开发者模式按钮都在更多设置中,但是小米手机有些不一样,更多设置中没有展示开发者选项,那么小米手机怎样打开开发者模式呢?
全栈程序员站长
2022/09/21
3.7K0
小米手机_如何打开开发者模式?[通俗易懂]
JS打开摄像头并截图上传
要注意的是,在chrome以外的浏览器中,使用摄像头或多或少会出现一些问题,可能也是老问题了,所以以下代码主要基于chrome使用
书童小二
2018/09/03
5.9K0
JS打开摄像头并截图上传
webrtc之STUN、TURN、打开摄像头实战
大家周末好,今天给大家分享的是webrtc第一篇文章,在之前的音视频文章里面没有分享过关于webrtc的内容;在上个周末分享了一篇关于播放器的文章,那篇文章整体上介绍了播放器的设计结构;我个人的学习路线,主要分为两大方向:ffmpeg和webrtc,然后会具体到各种协议。
用户6280468
2022/03/21
2.2K0
webrtc之STUN、TURN、打开摄像头实战
D妹打开了摄像头并开始……
直播! 你没看错,D妹真的要直播了! 没有套路 成年人的世界再简单一点 不用猜D妹是长腿妹妹还是抠脚大汉 活生生的D妹就在直播间与你面对面 就问你来不来? 6月18日 从早上10点到晚上9点 开机整整11个小时 D妹跟你聊聊产品 唠嗑唠嗑 最重要的 当然是给你618大促-直播间专属最低价 域名解析、建站证书、云服务器一次性全购齐! 没有什么烧脑规则 没有什么骚操作 直接上秒杀价 直接抽大奖 羊毛都捋顺了 就等你来薅! 【618直播预告第一弹】 ↓ ↓ ↓ 下周 将会放出618直播预告第二弹
腾讯云DNSPod团队
2021/06/07
7660
html5打开摄像头
<!DOCTYPE html> <html lang="zh-cn"> <head> <meta content="text/html; charset=UTF-8" http-equiv="content-type"> <title>Smart Home - Camera</title> <link href="css/main.css" rel="stylesheet" type="text/css"> <script src="
李海彬
2018/03/20
2.3K0
WebRTC网页打开摄像头并录制视频
前面我们能打开本地摄像头,并且在网页上看到摄像头的预览图像。 本文我们使用MediaRecorder来录制视频。在网页上播放录制好的视频,并能提供下载功能。
落寞的鱼丶
2022/02/26
1.6K0
python PIL 打开\显示\保存图像
使用python进行数字图片处理,还得安装Pillow包。虽然python里面自带一个PIL(python images library), 但这个库现在已经停止更新了,所以使用Pillow, 它是由PIL发展而来的。
狼啸风云
2020/10/28
3.5K0
python PIL 打开\显示\保存图像
Git 如何切换到不同远程仓库
例如我们有一个项目 USRealEstate,当前使用的是微信的 Git,我们希望切换到 GitHub 上。
HoneyMoose
2020/08/01
1.2K0
Git 如何切换到不同远程仓库
ESP32-CAM使用+源码分析
PSRAM:pseudo SRAM,伪SRAM。它具有类SRAM的接口协议:给出地址、读、写命令,就可以实现存取,不像DRAM需要memory controller来控制内存单元定期数据刷新,因此结口简单;但它的内核是DRAM架构:1T1C一个晶体管一个电容构成存储cell,而传统SRAM需要6T即六个晶体管构成一个存储cell。由此结合,他可以实现类SRAM的接口有可实现较大的存储容量。(我们都知道大容量SRAM非常贵)
云深无际
2021/02/23
7.8K0
ESP32-CAM使用+源码分析
点击加载更多

相似问题

如何从视图模式自动切换到编辑模式,反之亦然。

13

打开Android摄像头,然后在新活动中打开捕获的图像

21

如何将jetpack摄像头预览从后面切换到前面,反之亦然?

11

如何在IPhone中将导航栏从横向模式切换到纵向模式,反之亦然

13

Android摄像头,保存图像,然后显示图像。

25
添加站长 进交流群

领取专属 10元无门槛券

AI混元助手 在线答疑

扫码加入开发者社群
关注 腾讯云开发者公众号

洞察 腾讯核心技术

剖析业界实践案例

扫码关注腾讯云开发者公众号
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
查看详情【社区公告】 技术创作特训营有奖征文