各种语言中Promise的源码实现
2017-12-10 / modified at 2022-04-04 / 473 words / 1 mins
️This article has been over 2 years since the last update.

在NodeJS/Netty/Java/AngularJS等框架中,均有Promise的异步API设计,本文将结合多个框架,分析Promise的设计思路。

综述

什么是Promise

Promise是一种异步非阻塞的编程风格,实现了链式观察调用,而不需要一堆callbak。

1
2
http.get("test.json")
.then(data -> console.log(data))

它目前主要在前端比较火,比如常见功能有

  • 请求网页时弹框验证码,输入后自动重试网页请求(配合拦截器使用)
  • Android启动页同时显示广告并加载数据,等全部完成后进入首屏
  • Netty/ElasticSearch中发送请求后,异步等待返回结果

常见实现原理

在Promise的各种实现中,主要有两种实现

  • 单线程/事件驱动的编程语言: 主要有Android,Node/浏览器(含AngularJS),它们有Handler.postMessage或者setTimeout这类方法实现将事件塞入队列末尾异步执行来模拟Promise
  • 传统多线程编程语言: 主要有Java/Netty等框架,它们基于JUC中的CAS等或者Monitor机制实现线程释放时间片等待

Node实现原理

如何使用setTimeout来包装Promise

AngularJS中$Q实现原理

在AngularJS(第一版)中,它在setTimeout的基础上维护了一个内部的asyncTask队列,并在$apply流程中的finally的$digest进行消费。$Q是不支持await等待的。

setTimeout的原生implement与libuv

执行如下命令

1
2
# 下载NodeJS稳定版,并不保留历史记录
git clone https://github.com/nodejs/node.git -b v8.x --depth=1

这里可以看出,setTimeout由libev实现,调用链如下

1
2
lib/timers.js: createSingleTimeout

Android实现原理

如何用Handler包装Promise

比如这里仅仅一个文件就全部实现了,无非就是以前的Handle包装了一道。但是在Android中的Promise的设计API太丑,而且功能又没RxJava全,导致火不起来。

Android中的Handler与epoll