千家信息网

从C#到TypeScript - Promise

发表于:2026-10-31 作者:千家信息网编辑
千家信息网最后更新 2026年10月31日,从C#到TypeScript - Promise背景相信之前用过JavaScript的朋友都碰到过异步回调地狱(callback hell),N多个回调的嵌套不仅让代码读起来十分困难,维护起来也很不方
千家信息网最后更新 2026年10月31日从C#到TypeScript - Promise

从C#到TypeScript - Promise

背景

相信之前用过JavaScript的朋友都碰到过异步回调地狱(callback hell),N多个回调的嵌套不仅让代码读起来十分困难,维护起来也很不方便。
其实C#在Task出现之前也是有类似场景的,Async Programming Mode时代,用Action和Func做回调也很流行,不过也是意识到太多的回调嵌套代码可读性差且维护不易,微软引入了Task和Task-based Async Pattern。
虽然不知道是哪个语言最早有这个概念,但相信是C#把async await带到流行语言的舞台,接着其他语言也以不同的形式支持async await,如Python, Dart, Swift等。
JavaScript同样在ES6开始支持Promise和Generator,并在ES7中提出支持async await的议案。

这篇先来看看Promise:

Promise的特点

Promise之于TypeScript,相当于Task之于C#,只有返回Promise的函数才能使用async await。
Promise其实就是一个可以获取异步结果,并封装了一些异步操作的对象。
有三个状态:
pending: 进行中
resolved: 成功
rejected: 失败
并且这三个状态只有两种转换:pending->resolved、pending->rejected,不是成功就是失败,并没有多余的状态转换。
这两种转换都是由异步返回的结果给定的,成功取回数据就是resolved,取数据出异常就是rejected。
也因此,这转换过后的结果就是固定的了,不可能在转换过后还会变回pending或其他状态。
Promise不能在任务进行中取消,只能等结果返回,这点上不如C#的Task,Task可以通过CancelTaskToken来取消任务。

Promise的使用

可以直接new一个Promise对象,构造函数的参数是一个有两个参数的函数。
这两个参数一个是resove,用来在异步操作成功后调用,并把异步结果传出去,调用resove后状态就由pending->resolved。
另一个是reject,用来在失败或异常时调用,并把错误消息传出去,调用reject后状态由pending->rejected。

var promise = new Promise(function(resolve, reject) {    });

通常需要在成功或失败后做一些操作,这时需要then来做这个事,then可以有两个函数参数,第一个是成功后调用的,第二个是失败调用的,第二个是可选的。
另外,then返回的也是一个Promise,不过不是原来的那个,而是新new出来的,这样可以链式调用,then后面再接then。

// 函数参数用lambda表达式写更简洁promise.then(success => {    console.info(success);}, error => {    console.info(error);}).then(()=>console.info('finish'));

嵌套的Promise

在实际场景中,我们可能需要在一个异步操作后再接个异步操作,这样就会有Promise的嵌套操作。
下面的代码显示的是Promise的嵌套操作:
p1先打印"start",延时两秒打印"p1"。
p2在p1完成后延时两秒打印"p2"。

function delay(): Promise{    return new Promise((resolve, reject)=>{setTimeout(()=>resolve(), 2000)});}let p1 = new Promise((resolve, reject) => {    console.info('start');     delay().then(()=>{        console.info('p1');         resolve()    });});let p2 = new Promise((resolve, reject) => {    p1.then(()=>delay().then(()=>resolve()));});p2.then(()=>console.info('p2'));

异常处理

上面提到Promise出错时把状态变为rejected并把错误消息传给reject函数,在then里面调用reject函数就可以显示异常。
不过这样写显得不是很友好,Promise还有个catch函数专门用来处理错误异常。
而且Promise的异常是冒泡传递的,最后面写一个catch就可以捕获到前面所有promise可能发生的异常,如果用reject就需要每个都写。
所以reject函数一般就不需要在then里面写,在后面跟个catch就可以了。

new Promise(function(resolve, reject) {  throw new Error('error');}).catch(function(error) {  console.info(error); // Error: error});

也如上面所说状态只有两种变化且一旦变化就固定下来,所以如果已经在Promise里执行了resolve,再throw异常是没用的,catch不到,因为状态已经变成resolved。

new Promise(function(resolve, reject) {    resolve('success');    throw new Error('error');}).catch(function(error) {    console.info(error); // 不会执行到这里});

另外,catch里的代码也可能出异常,所以catch后面也还可以跟catch的议案。

new Promise(function(resolve, reject) {    throw new Error('error');}).catch(function(error) {    console.info(error);  // Error: error    throw new Error('catch error');}).catch(function(error){    console.info(error); // Error: catch error   };

BlueBird的 finally 和 done

异常的try...catch后面可以跟finally来执行必须要执行的代码,Promise原生并不支持,可以引入BlueBird的扩展库来支持。
另外还有done在最后面来表示执行结束并抛出可能出现的异常,比如最后一个catch代码块里的异常。

let p = new Promise(function(resolve, reject) {    x = 2;  // error, 没有声明x变量    resolve('success');}).catch(function(error) {    console.info(error); }).finally(()=>{ // 总会执行这里    console.info('finish');    y = 2;  // error, 没有声明y变量}).done(); try{    p.then(()=>console.info('done'));} catch (e){    console.info(e); // 由于最后面的done,所以会把finally里的异常抛出来,如果没有done则不会执行到这里}

并行执行Promise

虽然JavaScript是单线程语言,但并不妨碍它执行一些IO并行操作,如不阻塞发出http request,然后异步等待。
Promise除了用then来顺序执行外,也同样可以不阻塞同时执行多个Promise然后等所有结果返回再进行后续操作。
C#的Task有个WhenAll的静态方法来做这个事,Promise则是用all方法达到同样目的。
all方法接受实现Iterator接口的对象,比如数组。

let p = Promise.all([p1, p2, p3]);

all返回的是一个新的Promise- p,p的状态是由p1, p2, p3同时决定的:

p.resolved = p1.resolve && p2.resolve && p3.resolvep.rejected = p1.rejected || p2.rejected || p3.rejected

也就是说p的成功需要p1,p2,p3都成功,而只要p1, p2, p3里有任何一个失败则p失败并退出。

Promise还有一个方法race同样是并行执行多个Promise,不同于all的是它的成功状态和错误状态一样,只要有一个成功就成功,如同C# Task的Any方法。


状态 成功 函数 C# 代码 结果 参数 就是 方法 支持 语言 错误 两个 只有 多个 对象 三个 任务 变量 同时 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 云南咖啡 湖北九亚互联网络科技有限公司 华服互联网科技靠谱吗 科技股互联网 互联网科技公司税收优惠 有马互联网科技 郑州华宇互联网科技 富国互联网科技创新基金 上海电发互联网科技有限公司 现代科技和互联网有关系吗 互联网之后的科技是什么 广州市恰铎互联网科技有限公司 互联网科技和信息 2021互联网科技公司排名 银行科技岗属于互联网吗 本届互联网大会上的黑科技 半导体行业属于互联网高科技类吗 杭州融税互联网科技有限公司 科技互联网专业工作会议发言稿 10位科技互联网大佬 广州为想互联网科技有限公司 互联网科技公司经营范围 互联网女皇 腾讯科技 深圳卡尔迅互联网科技有限公司怎么样 小米互联网科技园设置 彤创互联网科技有限公司 互联网数据科技专业 互联网科技快讯热点 九思连强互联网电子科技有限公司 河南商务圈互联网科技有限公司
0