异步是ES6中使用频率最高的特性之一,也是面试中经常会被问到的问题,特此整理了相应的笔记

一、Promise的三种状态

pending-异步操作没有结束

fulfilled-异步操作已成功结束,最常见的就是在promise对象中返回resolve()

rejected-异步操作未成功,可能是有错误等,最常见的就是在promise对象中返回reject()

二、Promise的几大特性

1.立即执行特性

当实例化了一个Promise对象时,作为Promise参数传入的函数是会被立即执行的,只是其中执行的代码可以是异步代码。

特别需要注意的是,不能理解为调用.then()时Promise参数中的函数代码才开始执行

var p = new Promise(function(resolve, reject){
console.log("create a promise");
resolve("success");
}); p.then(function(value){
console.log(value);
});
console.log("after new Promise"); 

控制台输出结果

"create a promise"
"after new Promise"
"success"
2.then()方法中的回调函数是异步执行的
在上面的代码中console.log("after new Promise"); 虽然是在.then()方法后面调用,但是却先执行了,说明了then()的回调函数是异步执行的,需要等同步代码执行完了才会执行。
3.状态不可逆
当一个Promise对象的状态变为fulfilled或rejected后再改变状态是无效的
var p2 = new Promise(function(resolve, reject){
resolve("success");
resolve("suceess2");
});
p2.then(function(value){
 console.log(value);
});

控制台输出的结果是sucess而不是sucess2

4.链式调用

  • Promise对象出现的目的就是避免回调嵌套,避免回调嵌套的手段就是使用链式调用。链式调用的实现原理实现中很简单,就是在每个方法中返回一个相同类型的对象。
  • 不管是then()还是catch,不管使不使用return最终都会返回一个新的Promise实例。
  • 没有return时默认返回一个状态为fulfilled的对象,如果在then中抛出异常则返回一个rejected状态的对象;
  • 使用return时可以返回一个指定状态的Promise实例,也可以返回为普通值,当返回的是普通值时,实际上JS引擎会进行包装
var p = new Promise(function(resolve, reject){
resolve(1);
});
p.then(function(value){ //第一个then
console.log(value);
return value*2;
}).then(function(value){ //第二个then
console.log(value);
}).then(function(value){ //第三个then
console.log(value);
return Promise.resolve('resolve');
}).then(function(value){ //第四个then
console.log(value);
return Promise.reject('reject');
}).then(function(value){ //第五个then
console.log('resolve: '+ value);
}, function(err){
console.log('reject: ' + err);
})
  •  then中的Promise,必须在then内部再次使用then或catch进行处理,不然外层的then或catch无法捕获到状态

    var p = new Promise(function(resolve, reject){
    setTimeout(resolve('我是在then里调用的'),50)
    });
    var p2=function(){
    return new Promise(function(resolve, reject){
    setTimeout(resolve('放在第一个then中执行'),50)
    });
    }
    p.then(function(value){
    console.log('第一个then')
    p2()
    })
    .then(()=>{
    console.log('第二个then语句')
    })
    .catch((e)=>{
    console.log(e)
    })

上面的代码在p的第一个then中又调用了一个Promise-p2,此时p2没有没用then()或catch(),因此该then方法直接把控制权转给了后面的then或catch,控制台输出的结果如下

---第一个then

---第二个then

当我们把p2()改成p2().then((e)=>console.log(e))时,最外面一层的第二个then会进行等待:

---第一个then

---放在第一个then中执行

---第二个then

三、resolve和reject中的返回值是Promise类型对象时的处理机制

既可以在执行器中使用resolve(xxx)和reject(xxx),也可以使用Promise.resolve(xxx)和Promise.reject(xxx)来返回对象的执行状态,如果返回值是一个Promise类型的对象时情况比较有趣。

如果xxx是一个Promise类型,resolve(xxx)或Promise.resolve(xxx)会等待xxx的执行状态,并把XXX返回的状态做为对象的最终状态。

var p2 = new Promise(function(resolve, reject){
resolve(Promise.reject('reject')); //resolve中是一个执行失败的状态,因此p2的状态为rejected
});
p2.catch((err)=>console.log(err))

reject(xxx)或Promise.reject(xxx)则相对简单粗暴,直接把对象的状态变为rejected,不会根据XXX的执行结果来改变自身状态

var p2 = new Promise(function(resolve, reject){
reject(Promise.resolve('resolve'));
});
p2.catch((e)=>{
console.log(e)
})
var p3=Promise.reject(Promise.resolve('成功状态'))
p3.catch((e)=>{
console.log(e)
})

四、Promise中的错误

1.既可以使用throw语句,也可以使用reject,代码如下:

var p = new Promise(function(resolve, reject){
throw new Error('显示抛出一个错误')
//上面的代码等同于
try{
throw new Error('显示抛出一个错误')
}
catch(ex){
reject(ex)
}
});

2.抛出的错误可以使用then(null,(err)=>{...})也可以使用.catch((err)=>{})来捕获,当使用链式调用时,后面的catch可以捕获前面的错误

var p = new Promise(function(resolve, reject){
throw new Error('显示抛出一个错误')
});
//异常处理
p.then(null,function(err){
console.log(err.message);
return Promise.reject('返回一个reject')
})
.catch((err)=>{console.log(err)})

3.es2018新增了.finally(),不管Promise实例最终返回什么状态,都可以被该方法捕获到

promise
.then(result => {···})
.catch(error => {···})
.finally(() => {···});

4.错误处理钩子

未使用上面的错误处理机制时,可以监听unhandledrejection事件和rejectionhandled事件来获取错误

unhandledRejection :当一个 Promise 被拒绝、而在事件循环的一个轮次中没有任何拒 绝处理函数被调用,该事件就会被触发;

rejectionHandled :若一个 Promise 被拒绝、并在事件循环的一个轮次之后再有拒绝处 理函数被调用,该事件就会被触发。

在node.js中使用process.on('xxxx', (reason, promise) => ···)来监听事件,在window中使用window.addEventListener('unhandledrejection', event =>...),浏览器的event对象有三个属性

type :      事件的名称( "unhandledrejection" 或 "rejectionhandled" );
promise :被拒绝的 Promise 对象;
reason :  Promise 中的拒绝值(拒绝原因)。

Promise关键知识的更多相关文章

  1. iOS之UI--通讯录的实例关键知识技术点积累

    通讯录的实例关键知识技术点积累 效果展示: 作为博文笔记,既然是笔记,目的是为了能够以后做这个项目能够快速上手,如果这是我下一次阅览这个博文笔记,那么我应该先空手从零开始做,需求也就是这个项目的展示效 ...

  2. promise 基础知识

    promise 基础知识 proise:1.Promise是异步编程的一种解决方案,它有三种状态,分别是pending-进行中.resolved-已完成.rejected-已失败2.创建实例//met ...

  3. 在react native用到的javascript 的一些关键知识(整理中)

    发现了一个讲解javascript的好网站,分享一下,讲的非常棒! 注意,这些文章都可以选择中文进行阅读! 下面这个连接是关于prototype的: https://developer.mozilla ...

  4. android关键知识

    1.handler 与Looper 与MessageQueue .Message关系 handler:是处理主线程(ui线程)处理耗时操作的线程,通过post message到MessageQueue ...

  5. Kubernetes集群部署关键知识总结

    Kubernetes集群部署需要安装的组件东西很多,过程复杂,对服务器环境要求很苛刻,最好是能连外网的环境下安装,有些组件还需要连google服务器下载,这一点一般很难满足,因此最好是能提前下载好准备 ...

  6. 2 js的20/80关键知识

    1. 2 var a = 1; undefined a 1 alert(a); undefined var b = true; var c = "Hi"; undefined al ...

  7. C++关键知识

    <精通MFC>第一章节整理复习 //c++编程技术要点 /* //1.虚函数及多态的实现 //演示多态技术 #include <iostream> using namespac ...

  8. java关键知识汇总

    1.泛型理解 2.java或Java框架中常用的注解及其作用详解 3.三层架构和MVC的区别 4.jdk1.8手册(提取码:bidm) 5.Rocketmq原理&最佳实践 6.spring入门 ...

  9. 大白话讲解Promise(二)理解Promise规范

    上一篇我们讲解了ES6中Promise的用法,但是知道了用法还远远不够,作为一名专业的前端工程师,还必须通晓原理.所以,为了补全我们关于Promise的知识树,有必要理解Promise/A+规范,理解 ...

随机推荐

  1. ACM-ICPC (10/11)

    莫比乌斯 今年的多校比赛,莫比乌斯反演的题目经常出现,但是我们队对于这种题可以说是直接放掉,不是因为没学过,多少了解一些,但是也只是皮毛,导致根本就做不出来,其实想一想,其实次数多了,就可以看出原因了 ...

  2. ASP.NET SignalR 与LayIM配合,轻松实现网站客服聊天室(五) 补充:历史记录 和 消息提醒

    有开发者提问怎么做历史记录功能和即使不打开聊天窗口有消息提醒功能.简单抽时间写了点代码.不过只是基本思路,具体细节没有实现. 正如前几篇博客中提到的,读取历史记录什么时候读取呢?按照常理,应该是打开聊 ...

  3. AngularJS 控制器函数

    <!DOCTYPE html><html><head><meta http-equiv="Content-Type" content=&q ...

  4. JavaScript js调用堆栈(二)

    本文主要介绍JavaScript的内存空间 var a = 20; var b = 'abc'; var c = true; var d = { m: 20 } 首先需要对栈(stack),堆(hea ...

  5. SpringBoot非官方教程 | 第十四篇:在springboot中用redis实现消息队列

    转载请标明出处: 原文首发于:https://www.fangzhipeng.com/springboot/2017/07/11/springboot14-redis-mq/ 本文出自方志朋的博客 这 ...

  6. Vue--- 使用vuex使用流程 1.0

    Vuex 1.安装vuex npm install  -save vuex 2. 引入 创建store文件夹目录 创建 vuex     指挥公共目录    store['state','action ...

  7. c/c++ 表白小程序

    1.开发工具: vs  vc(任选一个) 2.准备材料 : a.一首音乐 (注意:音乐要求重命名为  “x”  ) b.20张图片(注意: 图片要求重命名为  “1”  "2"   ...

  8. 免安装版Tomcat9中间件的安装

    [环境准备] OS版本:Windows10.64位 Tomcat版本:apache_tomcat9.0.7.zip免安装版 [彻底卸载已安装的Tomcat中间件] 01:由于是免安装版本,因此直接删除 ...

  9. Co. - Microsoft - Windows - Dos命令

    DOS命令 cd .. 是进入上一层目录,cd \ 是进入根目录 我们来重申下%~dp0和%cd%的区别, %cd%和%~dp0都能用来表示当前目录,但是他们在不同的使用场景下,功能却不相同: %cd ...

  10. Java OOP——第一章 对象和封装

    1.软件出现的目的: 用计算机的语言描述现实世界 用计算机解决现实世界的问题   ◆面向对象设计和开发程序的好处:    交流更加流畅    提高设计和开发效率 计算机语言的发展向接近人的思维方式演变 ...