异步是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. Codeforces 396A 数论,组合数学

    题意:给一个a数组,求b 数组的方案数,但是要求两者乘积相同. 分析: 不可能将它们乘起来,对于每个数质因数分解,得到每个质因子个数,遍历这些质因子,将某个质因子放到 对应的盒子里面,可以不放,方案数 ...

  2. 【[NOI2018]你的名字】

    题目 可能是一个乱搞做法,同时也跪求有人能帮我分析一下复杂度 还是先来看比较简单的\(68pts\),也就是\(l=1,r=|S|\)的情况 我们可以直接把\(S\)串和所有的\(T\)串一起建一个广 ...

  3. html或jsp页面自动提交,无需每次重启服务

    从eclipse转到idea遇到各种问题,之前eclipse可以自动保存页面内容无需重启服务,但是idea不可以,网上找了n种办法也没用,可能版本不一样吧,把我的解决方法纪录一下,方便以后有人遇到这个 ...

  4. SpringMVC学习记录三——8 springmvc和mybatis整合

    8      springmvc和mybatis整合 8.1      需求 使用springmvc和mybatis完成商品列表查询. 8.2      整合思路 springmvc+mybaits的 ...

  5. P1272

    P1272 重建道路 题目描述 一场可怕的地震后,人们用N个牲口棚(1≤N≤150,编号1..N)重建了农夫John的牧场.由于人们没有时间建设多余的道路,所以现在从一个牲口棚到另一个牲口棚的道路是惟 ...

  6. data-ng-show 指令

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

  7. java类的初始化程序块以及被实例化时候的执行顺序

    初始化块:在类实例化过程中初始化执行顺序是先执行静态初始化块,然后执行普通初始化块,最后执行构造函数,而且静态初始化只在第一次被实例化时执行且只执行一次.public class HelloWorld ...

  8. xcode7--iOS开发---将app打包发布至app store

    时隔3个月再次接触应用打包,又是一顿折腾 说说这次的感受吧: 变得是打包时间减少到4小时(其中大部分时间还是xcode7或者是iOS9的原因),不变的是还是一如既往的坑!! 好了,废话不多说,下面讲讲 ...

  9. 混合应用开发:Phonegap VS AppCan

    混合应用开发:Phonegap VS AppCan 简介 Phonegap PhoneGap是一个用基于HTML,CSS和JavaScript的,创建移动跨平台移动应用程序的快速开发平台.它使开发者能 ...

  10. iOS之点击通知栏跳转应用的相关页面

    当远程推送通知到达应用,有3个相关的方法是用来处理这个通知的. - (BOOL)application:(UIApplication *)application didFinishLaunchingW ...