这篇文章说说我对promise的理解。

promise在ES6之前就有的写法,在ES6中写入了语言标准,于是就有了原生promise对象。

promise对象能更好的改善异步操作的回调地狱,把多层嵌套扁平化,看上去像同步执行的代码,更容易阅读和理解。由于js语法的灵活多变,也导致了promise的写法多样。

promise有三种状态来表示当前执行的进度,pending,resolve,reject。promise执行后,默认是pending状态,意思是正在执行,promise有两种状态变化,并且是不可逆的,第一种就是从pending到resolve,从正在执行到执行成功,第二种是pending到reject,从执行中到执行失败。

promise一旦开始执行,就不能停止,直到执行结束。

如果不设置回调函数,Promise内部抛出的错误,不会反应到外部。

当处于Pending状态时,无法得知目前进展到哪一个阶段(刚刚开始还是即将完成)。

下面我就针对promise的常规用法,链式调用,all方法,race方法这四方面来说说我对promise的理解。

先说常规用法:

let promise = new Promise(function (resolve,reject){let res = 1+2+3;if(res>1){resolve(res);}else{reject("err");}
});
//结果接收方式1
promise.then(function (res){console.log(res);
},function (err){console.log(err);
});
//结果接收方式2
promise.then(function (res){console.log(res);
}).catch(function (err){console.log(err);
});
//结果接收方式3
promise.then(function (res){console.log(res);
});
promise.catch(function (err){console.log(err);
});

常规用法就是声明一个promise对象,写入逻辑,根据逻辑的返回结果确定是执行成功还是执行失败,执行成功就调用resolve方法,该方法接受一个参数,可以把逻辑返回的结果传到外面来使用。执行失败可以调用reject方法,该方法也可以传数据到外部,一般是传错误信息。

在上面的代码中我写了三种结果接收方式,先说第一种:

//结果接收方式1
promise.then(function (res){console.log(res);
},function (err){console.log(err);
});

promise有then方法,可以传两个参数,两个参数都是function,用来接收数据,第一个参数是接收逻辑执行成功的返回值,第二个参数接收逻辑执行失败的返回值。当然这种看上去也会有一些嵌套的感觉,我一般是不用这种写法的。

//结果接收方式2
promise.then(function (res){console.log(res);
}).catch(function (err){console.log(err);
});

我的个人理解是promise提供了then方法,又提供了catch方法,就是为了分别接收不同的逻辑执行结果的,then方法就是为了接收成功返回的结果,那相应的,catch方法就是为了接收失败返回的结果,node.js中链式调用很常见,这种写法也是一种链式调用,我是比较喜欢这种用法的。

//结果接收方式3
promise.then(function (res){console.log(res);
});
promise.catch(function (err){console.log(err);
});

当然,既然promise提供了then和catch两个方法接收结果,自然也可以用方法3来接收逻辑返回的结果,有些童鞋喜欢看起来很明朗的代码风格,那就是这种了,这种只是比第二种方式多了(promise对象.)这么一点代码。其实看起来是挺工整的。

下面再说说promise的链式调用:

假设一种情况:你在A文件里记录的B文件的名字,在B文件里记录的C的名字,又在C文件里记录的D文件的名字,你现在知道A文件的名字,想得到D文件的内容,该怎么来写呢?我会这样写:

new Promise(function(resolve,reject){let res1 = 1;//res1逻辑if(res1){console.log("res1",res1);resolve(res1);}else{reject('new Error1()');}
}).then(function (res){return new Promise(function (resolve,reject){let res2 = 2+res;//res2逻辑if(res2){console.log("res2",res2);resolve(res2);}else{reject("new Error2");}});
}).then(function (res){return new Promise(function (resolve,reject){let res3 = 3 + res;//res3逻辑if(res3){console.log("res3",res3);resolve(res3);}else{reject('new Error3');}});
}).then(function (res){console.log("res",res);//res3结果}
);

先在res1逻辑中用A文件的名字读取A文件的内容,得到的结果resolve出去。在then中接收。

然后在res2逻辑中取得A文件内容,解析出B文件名字,再读取B文件内容,resolve出去。在then中接收,一直到res3结果这里得到D文件的内容,如果是用回调函数的话估计就要嵌套很多层了,而用promise,就能很直观的看清代码走势,是不是很简单,当然这一段代码我一直觉得应该有更简洁的写法,但无奈本领不到家,只能写成这样了,如果有大神看见的话,请赐教。

这一段就是promise的链式调用,写个简洁的就是

new Promise().then().then().then();

好吧,下面说说promise的all方法:

function test(value){let promise = new Promise(function (resolve,reject){value = value * 2;if(value){resolve(value);}else{reject("err"+value);}});return promise;
}let promArr = [1,2,3,4,5,6,7,8,9,10].map(function (i){return test(i);
});
Promise.all(promArr).then(function (posts){console.log(posts);
}).catch(function (err){console.log(err);
});

这里假设我需要执行10个异步操作,并把他们的结果放到一个数组里同时传给一个方法,那all方法就能派上用场了,在这里需要重点说明一下:如果10个promise都是返回成功的话,也就是promise内部逻辑都是调用了resolve(value)方法的话,promise.then才能接收到最终的10个promise的结果组成的数组,就是上面代码中的posts,假如其中一个promise执行失败,那么,不好意思,你就只能在catch中收到这个失败的promise返回的错误信息了,是的,只能收到执行失败的promise返回的错误信息,这就是all方法。大概可以理解成这样:

let a = true && true && true && true;

当所有的表达式都为true时a才能等于true,有一个表达式为false时,a就不能等于true;

下面再说一下race方法。这个方法有点奇特,举个例子,一个孕妇怀了四胞胎,那谁是老大呢,当然是先出生的是老大了,而race方法最奇特的地方就在于我只想知道老大是谁,不管后面谁是老二老三,或者说race是一个非常狠心的父亲,只想要老大这一个孩子,后面的小孩一个也不要,就算出生了也是扔在医院不管不问。看代码:

function test(value){let promise = new Promise(function (resolve,reject){setTimeout(function (){resolve(value);},Math.random() * 10000);});return promise;
}let promArr = [1,2,3,4,5,6,7,8,9,10].map(function (i){return test(i);
});
Promise.race(promArr).then(function (post){console.log('post',post);
}).catch(function (err){console.log('err',err);
}).finally(function (){console.log('finally');
});

这个例子的意思是有10个promise,每个的逻辑都是延时一段时间,时间随机,谁先执行完谁就先返回。

最后的结果是post只能得到一个值,但别的延时还没执行完之前,这段程序不会结束,那也就意味着其他9个promise仍然会执行到底,但我们是获取不到他们9个的结果的,只能得到第一个返回的promise的结果。

恩。就先暂时说这么多吧,promise还有一个done方法和finally方法,done方法是放在then链最后,是用来捕获中间发生的任何异常的,这个没有试验,finally据说是不论then和catch执行了哪一个都会执行finally方法,但我试验了却报错了,有兴趣的同学可以研究一下。

转载于:https://blog.51cto.com/wuzishu/1732610

node.js学习笔记之promise相关推荐

  1. 千锋Node.js学习笔记

    千锋Node.js学习笔记 文章目录 千锋Node.js学习笔记 写在前面 1. 认识Node.js 2. NVM 3. NPM 4. NRM 5. NPX 6. 模块/包与CommonJS 7. 常 ...

  2. node.js学习笔记

    # node.js学习笔记标签(空格分隔): node.js---## 一 内置模块学习 ### 1. http 模块 ``` //1 导入http模块 const http =require('ht ...

  3. node.js学习笔记14—微型社交网站

    node.js学习笔记14-微型社交网站 1.功能分析 微博是以用户为中心,因此需要有注册和登录功能. 微博最核心的功能是信息的发表,这个功能包括许多方面,包括:数据库访问,前端显示等. 一个完整的微 ...

  4. Node.js学习笔记8

    Node.js学习笔记8 HTTP服务器与客户端 Node.js的http模块,封装了一个高效的HTTP服务器和一个简易的HTTP客户端 http.server是一个基于事件的HTTP服务器,核心由N ...

  5. node.js学习笔记5——核心模块1

    node.js学习笔记5--核心模块1 Node.js核心模块主要内容包括:(1)全局对象 (2)常用工具 (3)事件机制 (4)文件系统访问 (5)HTTP服务器与客户端 一: 全局对象 Node. ...

  6. node.js 学习笔记(二)模板引擎和C/S渲染

    node.js 学习笔记(二)模板引擎和C/S渲染 文章目录 node.js 学习笔记(二)模板引擎和C/S渲染 一.初步实现Apache功能 1.1 使用模板引擎 1.2 在 node 中使用模板引 ...

  7. 唤醒手腕 - 前端服务器端开发 Node.Js 学习笔记(学习中,更新中)

    唤醒手腕 - Node.Js 学习笔记 唤醒手腕个人的学习记录,时间在2021年12月13日 ~ 2021年12月14日,学习方式看官方文档和B站视频,如有错误或者代码问题的地方,欢迎C站大佬能够帮忙 ...

  8. node.js学习笔记Day2

    目录 第一部分:用npm安装mysql模块 第二部分:在项目内创建 第三部分:引用opreateDB方法 第四部分:解决异步方法的问题 第五部分:关于热启动 第六部分:关于接收参数和带参查询数据 今天 ...

  9. node.js学习笔记 - 文件上传(并用七牛云托管)

    文章目录 环境搭建 准备工作 安装相关依赖 代码实现 执行 环境搭建 准备工作 提示:本文采用ts来构建环境,要是以js构建则取掉类型定义即可. 初始化项目 创建目录fileUpload-demo- ...

最新文章

  1. mapreduce中设置自定义的输入类,进行文本解析(默认以tab键为分隔符)
  2. ABAP源程序---发票校验明细表
  3. WCF系列学习笔记4之绑定详解
  4. 20120907学习笔记
  5. 【HDU - 3394】Railway(点双连通分量,Tarjan算法,思维tricks)
  6. PHP动态白云为背景的引导页-个人主页源码
  7. Spring Boot+Vaadin 14项目初始化
  8. 已解决:home目录下ubuntu文件夹被误删。。。。
  9. 本地mongochef连接其他计算机上的数据库认证失败解决方法
  10. 基于SpringBoot的个人博客系统【完整项目源码】
  11. 三菱plc分拣程序_基于三菱PLC控制的物料分拣系统设计与实现
  12. android毕业论文结论,毕业论文经典结束语
  13. android ios 微信 备份通讯录备份通讯录备份通讯录,苹果手机怎么备份通讯录?手机通讯录微信联系人备份教程...
  14. runOnUiThread简单应用
  15. jstree使用教程
  16. 斗拱展开面积表_古建筑斗拱换算问题
  17. MFC中MediaPlayer基本功能使用
  18. 自动驾驶系统入门(八)- 自动驾驶仿真技术
  19. 怎么查看显卡算力(附nvidia显卡算力表)
  20. 图书管理系统(简单版)面向对象程序设计c++

热门文章

  1. access“idno”字段改为文本型_结构化文本计算示例(一)
  2. 基于python的压测工具_Python Locust性能测试简介及框架实践
  3. Spring学习笔记:1(初步认识概念)
  4. sparkcore分区_Spark学习:Spark源码和调优简介 Spark Core (二)
  5. 获取服务器路径的方式 【记录】
  6. CSS之常用选择器(元素、id、类、通配选择器)
  7. 微信小程序打开预览下载的文件
  8. iOS 数组中的模型去重
  9. MLeaksFinder简单实现原理
  10. 【iOS官方文档翻译】iOS蓝牙的基本概念