Promise入门

小小码农,可笑可笑
• 阅读 1469

ES6为什么推出Promise

Promise 是ES6新增的引用类型,让我们的异步逻辑代码更加优雅。

异步就相当于你会了影分身,本来你只能同一时间做一个事情,但是当你有了分身之后,你可以和他同一时间做不同的事情。

Promise入门

所以,异步增加了我们事情完成的效率,这也就是我们常说的避免进程等待一个长时间的线程操作,同时执行,减少耗时,增加性能。

异步是JavaScript的基础,之前的异步实现并不理想。以前,想要表明一个异步操作的完成,只能通过回调函数来完成,当异步当中还有异步,如此反复多次,就是常说的回调噩梦

但是当有了Promise就不一样了,我们不需要回调嵌套,逻辑清晰、代码优雅的完成了异步操作。

我们来对比下吧。以嵌套三次为例。不需要看懂代码,只需要对比下哪种更优雅。

以前异步嵌套

//定义一个异步函数
function double(value, success, failure) {
  setTimeout(() => {
    try {
      if(typeof value === 'number'){
        success(2 * value);
      }else{
        throw '参数必须是数字';
      }
    } catch (error) {
      failure(error);
    }
  }, 100);
}

//注意这里。这是成功回调。z用到了y,y用到了x,所以需要嵌套3层
const successCallback = (x)=>{
  double(x,(y)=>{
    double(y,(z)=>{
      console.log('success:',z);
    })
  })
}
//失败回调
const failureCallback = (e)=>{
  console.log('failure',e);
}
double(3, successCallback, failureCallback);

有了Promise的异步多层回调

//定义一个工厂方法
function doublePromise(value){
  let p1 = new Promise((resolve,reject)=>{
    if(typeof value === 'number'){
      setTimeout(()=>{
        try {
          resolve(2*value);
          console.log('success:',2*value);
        } catch (error) {
            reject(error);
            console.log('failure',error);
        }
      } , 100);
    }else{
      throw '参数必须是数字';
    }
  })
  return p1
}

//promise将异步串行化,避免了回调噩梦
doublePromise(3).then((value1)=>{
  console.log(typeof value1)
  return doublePromise(value1)
}).then((value2)=>{
  console.log(value2)
  return doublePromise(value2)
})

目前还是三层的,越多的话就越发现Promise的优雅与简洁。

Promise(期约)

基本表现形式

new Promise((resolve,reject)=>{

})

Promise的三种状态:

  • 待定(pending)

new Promise((resolve,reject)=>{

})//Promise {<pending>}

未定义其他状态,且未改变其状态时,期约为pending状态

  • 兑现(fulfilled,也可称作解决,resolved)

new Promise((resolve,reject)=>{
   resolve()
})//Promise {<fulfilled>: undefined}
  • 拒绝(rejected)

new Promise((resolve,reject)=>{
   reject()
})//Promise {<rejected>: undefined}
  • 状态变更规则

注意!Promise从待定状态改变为兑现或拒绝,只能改变一次。

let p = new Promise((resolve,reject)=>{
    resolve();
    reject();
});
console.log('期约状态:',p)
//或许你以为是期约状态:Promise<rejected>,实际上是期约状态:Promise<resolved>

Promise初始状态并非一定是pedding(待定)状态:

let p1 = new Promise((resove,reject) => resove());
let p2 = Promise.resove();
//p1 和 p2两个都是解决期约

解决期约Promise.resolve()

解决期约(Promise.resolve())可包装任何非期约值,就算是错误对象,并只接受一个参数值!若参数为期约,则返回参数参数期约,可将外层期约看作个空包装。可以说Promise.resolve()是一个幂等方法。此幂等性还会保留期约传入的状态。类似我们学过的函数方程:f(f(x)) = f(x)

代码:

let p3 = Promise.resolve(1);
let p4 = Promise.resolve(p3);
console.log(p3===p4); //true

拒绝期约(Promise.reject())

拒绝期约(Promise.reject()),会实例化一个拒绝期约,并抛出一个异步错误。该错误不能通过try/catch捕获,只能通过拒绝处理程序捕获。参数如果传入一个期约,则这个期约将成为拒绝的理由。

代码:

let p = Promise.reject(Promise.resolve());
console.log('p:', p);
// p: Promise { <state>: "rejected", <reason>: Promise { "fulfilled" } }

Promise的实例方法

三个方法,一个处理方法,一个拒绝处理方法。一个无论拒绝还是处理都会执行的方法。

你跟我表白,我得告诉你我接受不接受吧,虽然很多渣男渣女吊着你,但是程序不会吊着你,除非没网,那个时候就是渣程序。还有无论接受不接受,不影响我找你借钱吧

Promise入门

处理方法then()

可以传两个参数,Promise.prototype.then(onResoved,onRejected)。返回值为一个新Promise对象

let p = new Promise((resolve,reject)=>{
    resolve('我接受你啦')
});
p.then(()=>{
    console.log('我同意我同意,你好帅哇,想给你大马猴')
})

拒绝处理方法catch()

类似一个语法糖,等同于Promise.prototype.then(null,onRejected)。返回值为一个新Promise对象

let p = new Promise((resolve,reject)=>{
    reject('不行!')
});
p.catch(()=>{
    console.log('你太丑了')
})

兑现或拒绝都会执行的方法finally()

返回值为一个新Promise对象

let p = new Promise((resolve,reject)=>{
    reject('不行!')
});
p.finally(()=>{
    console.log('不过你能借我点钱嘛?')
})

入门就到这里,下一篇深入。

点赞
收藏
评论区
推荐文章
blmius blmius
3年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
Karen110 Karen110
3年前
一篇文章带你了解JavaScript日期
日期对象允许您使用日期(年、月、日、小时、分钟、秒和毫秒)。一、JavaScript的日期格式一个JavaScript日期可以写为一个字符串:ThuFeb02201909:59:51GMT0800(中国标准时间)或者是一个数字:1486000791164写数字的日期,指定的毫秒数自1970年1月1日00:00:00到现在。1\.显示日期使用
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为
待兔 待兔
3个月前
手写Java HashMap源码
HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22
Karen110 Karen110
3年前
​一篇文章总结一下Python库中关于时间的常见操作
前言本次来总结一下关于Python时间的相关操作,有一个有趣的问题。如果你的业务用不到时间相关的操作,你的业务基本上会一直用不到。但是如果你的业务一旦用到了时间操作,你就会发现,淦,到处都是时间操作。。。所以思来想去,还是总结一下吧,本次会采用类型注解方式。time包importtime时间戳从1970年1月1日00:00:00标准时区诞生到现在
Stella981 Stella981
3年前
JavaScript中Promise 使用、原理以及实现过程
1.什么是Promisepromise是目前JS异步编程的主流解决方案,遵循Promises/A方案。2.Promise原理简析(1)promise本身相当于一个状态机,拥有三种状态pendingfulfilledrejected一个promise对象初始化时
Easter79 Easter79
3年前
Twitter的分布式自增ID算法snowflake (Java版)
概述分布式系统中,有一些需要使用全局唯一ID的场景,这种时候为了防止ID冲突可以使用36位的UUID,但是UUID有一些缺点,首先他相对比较长,另外UUID一般是无序的。有些时候我们希望能使用一种简单一些的ID,并且希望ID能够按照时间有序生成。而twitter的snowflake解决了这种需求,最初Twitter把存储系统从MySQL迁移
Wesley13 Wesley13
3年前
35岁是技术人的天花板吗?
35岁是技术人的天花板吗?我非常不认同“35岁现象”,人类没有那么脆弱,人类的智力不会说是35岁之后就停止发展,更不是说35岁之后就没有机会了。马云35岁还在教书,任正非35岁还在工厂上班。为什么技术人员到35岁就应该退役了呢?所以35岁根本就不是一个问题,我今年已经37岁了,我发现我才刚刚找到自己的节奏,刚刚上路。
Stella981 Stella981
3年前
JavaScript 异步编程
❝掌握JavaScript主流的异步任务处理(本篇文章内容输出来源:《拉钩教育大前端训练营》参阅《你不知道的JavaScript中卷》异步章节)❞JavaScrip采用单线程模式工作的原因,需要进行DOM操作,如果多个线程同时修改DOM浏览器无法知道以哪个线程为主。JavaScirpt分为:同步模式、异步模式同步
Easter79 Easter79
3年前
Spring如何优雅地发送异步发送通知?
题主应该想问的是在spring框架下如何开发一个“优雅的、异步的”的去执行一个功能吧?至于这个功能是发送一条MQ消息啊还是发送一份邮件、一条短信都可以,重要的是想异步且优雅的执行这些功能。从上面对题目的分析来看的话,题主可以参考一下我的解决办法和思路:1.异步代表着你需要开启一个单独的线程去做这个事情,这个事情做完了,这个线程需要及时的释放,避免