异步是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. 【洛谷P1966】火柴排队

    火柴排队 题目链接 ∑(ai​−bi​)^2=∑ai^2-2*∑ai*bi+∑bi^2 显然∑ai^2+∑bi^2是不变的,我们要让 2*∑ai*bi最大,才能使原式最小 然后我们一眼就可以看出来, ...

  2. hadoop核心逻辑shuffle代码分析-map端 (转)

    一直对书和各种介绍不太满意, 终于看到一篇比较好的了,迅速转载. 首先要推荐一下:http://www.alidata.org/archives/1470 阿里的大牛在上面的文章中比较详细的介绍了sh ...

  3. linux系统命令与常识

    之前短期学过linux,用到时才发现已经忘得一干二净了. 现在对学过的和了解到的做一个总结: 先明确一些使用工具: winscp : WinSCP是一个Windows环境下使用SSH的开源图形化SFT ...

  4. vue进阶语法及生命周期函数

    1.calss和style绑定 操作元素的 class 列表和内联样式style是数据绑定的一个常见需求,它两都是属性,所以可以通过v-bind来绑定 1.1绑定HTML class 可以给v-bin ...

  5. CTRL+F5 和F5 两种刷新有什么区别

  6. iOS-GCD使用详解

    前言 对初学者来说,GCD似乎是一道迈不过去的坎,很多人在同步.异步.串行.并行和死锁这几个名词的漩涡中渐渐放弃治疗.本文将使用图文表并茂的方式给大家形象地解释其中的原理和规律. 线程.任务和队列的概 ...

  7. c#最近博文结尾

    总结一下最近的内容.最近休息一段时间,学习了很多内容,研究了一些新的东西.也不说了.前面的博文主要内容. (1)分布式部署(etcd) (2) 分布式注意事项 (3)c#序列化(messagepack ...

  8. 在CentOS 7上搭建Docker环境

      Preface       We commonly use VMware or VirtualBox to install our Virtual Machines before.For the ...

  9. JavaScript实现Tab切换

    在网页开发中,常常会遇见很多Tab切换,Tab切换增加网页浏览的舒适性,对于开发人员特别常见,本文使用JS实现tab切换效果,仅对学习中遇到的知识点做一个总结. 效果图如下:     实现思路: 1. ...

  10. java常见面试问题.你一定会预见到。

    1判断一个char字符是不是数字:Character.isDigit(char).是数字返回true,反之返回false. 2字符串的toCharArray() 把字符串转换为字符数组.返回char[ ...