从C#到TypeScrip

来源:互联网 发布:跟团游推荐 知乎 编辑:程序博客网 时间:2024/05/29 20:01

总目录

  • 从C#到TypeScript - 类型

  • 从C#到TypeScript - 高级类型

  • 从C#到TypeScript - 变量

  • 从C#到TypeScript - 接口

  • 从C#到TypeScript - 类

  • 从C#到TypeScript - function

  • 从C#到TypeScript - 装饰器

  • 从C#到TypeScript - Promise

  • 从C#到TypeScript - Generator

  • 从C#到TypeScript - async await

  • 从C#到TypeScript - 元数据

从C#到TypeScript - Promise

背景

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

这篇先来看看Promise:

Promise的特点

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

function delay(): Promise<void>{    return new Promise<void>((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方法。

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



0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 资料员到期了怎么办 八大员挂靠社保怎么办 安许证三类人员不足了怎么办 考试准考证号写错了怎么办 科目一失约两次怎么办 钢筋送检两次不合格怎么办 公路原材料抽检不合格怎么办 混凝土回弹强度不合格怎么办 毕业证照片太丑怎么办 政审时找不到档案怎么办 劳动解除书开不出来怎么办 双流办健康证怎么办 户口本人数满了怎么办 二建有效期到了怎么办 二级建造师到期怎么办 网上选车牌号后怎么办 政府拖欠水利工程款怎么办 重庆造价员到期了怎么办 枕大神经发炎怎么办 塑钢推拉窗下沉怎么办 网上买东西数量不够怎么办 淘宝买东西数量不够怎么办 康佳遥控器坏了怎么办 电视机频幕脏了怎么办 极米遥控器失灵怎么办 电视遥控坏了怎么办 小米手机触摸屏失灵怎么办 oppo手机触摸屏失灵怎么办 苹果手机屏幕没反应怎么办 苹果6sp换屏卡顿怎么办 苹果4屏幕失灵怎么办 苹果手机老是卡怎么办 苹果手机卡机了怎么办 苹果手机卡屏了怎么办 苹果8手机老卡机怎么办 苹果手机不开机怎么办 手机开机后黑屏怎么办 苹果x手机黑屏怎么办 苹果7手机黑屏怎么办 苹果触控不灵敏怎么办 收银机触屏失灵怎么办