【ES6.0】- Promise对象

【ES6.0】- Promise对象

文章目录

  • [【ES6.0】- Promise对象](#【ES6.0】- Promise对象)
    • 一、概述
    • 二、Promise状态
    • 三、Promise方法
      • [3.1 Promise.prototype.then方法:链式操作](#3.1 Promise.prototype.then方法:链式操作)
      • [3.2 Promise.prototype.catch方法:捕捉错误](#3.2 Promise.prototype.catch方法:捕捉错误)
      • [3.3 Promise.race方法:捕捉错误](#3.3 Promise.race方法:捕捉错误)
      • [3.4 Promise.any()](#3.4 Promise.any())
      • [3.5 Promise.all()](#3.5 Promise.all())
      • [3.6 Promise.allSettled()](#3.6 Promise.allSettled())
    • 四、总结

一、概述

Promise是异步编程的一种解决方案,是一种javascript处理异步操作的一种常见方式。Promise是一种处理异步操作的设计模式,提供了一种更结构化,更可靠的方式来处理异步任务。

二、Promise状态

Promise异步操作有三种状态:pending(进行中)、fulfilled(已成功)和rejected(已失败)。除了异步操作的结果,任何其他操作都无法改变状态。

Promise对象只有:从pending变为fulfilled和从penging变为rejected的状态改变。只要处于fulfilled和rejected,状态就不会再变为resolved (已定型)。

Promise状态演示

js 复制代码
const pm1=new Promise(function(resolve,reject){
    resolve('resolve1')
    resolve('resolve2')
})

const pm2=new Promise(function(resolve,reject){
    resolve('resolve3')
    reject('reject1')
})

pm1.then(function(value){
    console.log('pm1->then->value',value)  //resolve1
})

pm2.then(function(value){
    console.log('pm2->then->value',value)  // resolve3
})

状态的缺点:

无法取消Promise,一旦新建它就会立即执行,无法中途取消。如果不设置回调函数,Promise内部抛出的错误,不会反应到外部。当处于pending状态时,无法得知目前进展到哪一个阶段。

三、Promise方法

3.1 Promise.prototype.then方法:链式操作

Promise.prototype.then方法返回的是一个新的Promise对象,因此可以采用链式写法:

javascript 复制代码
const pm1=new Promise(function(resolve,reject){
    resolve('resolve-01')
})
pm.then(function(value){
    console.log(value)
    return value+'-02'
}).then(function(value){
    console.log(value)
    return value+'-03'
}).then(function(value){
    console.log(value)
})

输出结果

shell 复制代码
resolve-01
resolve-01-02
resolve-01-02-03

上面的代码使用then方法,依次指定了两个回调函数。第一个回调函数完成以后,会将返回结果作为参数,传入第二个回调函数,第二个回调函数完成以后,会把返回值作为参数出入给第三个回调函数;依次直至结束。

如果前一个回调函数返回的是Promise对象,这个时一个回调函数就会等待该Promise对象有了运行结果才进一步调用

js 复制代码
const pmFun=(param)=>{
    return new Promise((resolve,reject)=>{
        setTimeout(()=>{
            if(param<100){
                resolve('输入值<100,传入值为:'+param)
            }else{
                reject('输入值>100,传入值为:'+param)
            }
        },2000)
    })
}
pmFun(50).then((resp)=>{
    console.log('then-1',resp)
    return pmFun(83)
}).then((resp)=>{
    console.log('then-2',resp)
})

输出结果:

shell 复制代码
输入值<100,传入值为:50
输入值<100,传入值为:82

Promisei的这种设计使得嵌套的异步操作,可以被很容易得到改写,从回调函数的"横向发展"改为"向下发展"。

3.2 Promise.prototype.catch方法:捕捉错误

Promise.prototype.catch方法是Promise.prototype.then(null,rejection)的别名,用于指定发生错误时回调函数。

js 复制代码
const pmFun=(param)=>{
    return new Promise((resolve,reject)=>{
        setTimeout(()=>{
            if(param<100){
                resolve('输入值<100,传入值为:'+param)
            }else{
                reject('输入值>100,传入值为:'+param)
            }
        },2000)
    })
}
pmFun(50).then((resp)=>{
    console.log('then-1',resp)
    return pmFun(83)
}).then((resp)=>{
     console.log('then-1',resp)
}).catch((resp)=>{
    console.log('catch',resp)
})

Promise对象的错误具有"冒泡"性质,会一直向后传递,直到被捕捉为止,也就是说,错误总是会被下一个catch语句捕捉。

3.3 Promise.race方法:捕捉错误

Promise.race()方法允许我们同时发起多个异步操作,并在其中一个操作解决(fulfilled)或拒绝(rejected)时得到结果。它的语法如下:

js 复制代码
Promise.race([promise1,promise2,..])

其中,promise1,promise2等为Promise对象数组。新的Promise的状态将与第一个解决或拒绝的Promise的状态相同。

js 复制代码
const p1=new Promise((resolve,reject)=>{
    setTimeout(resolve,2000,'one')
})
const p2=new Promise((resolve,reject)=>{
    setTimeout(resolve,1000,'two')
})
const p3=new Promise((resolve,reject)=>{
    setTimeout(resolve,3000,'three')
})
const p3=new Promise((resolve,reject)=>{
    setTimeout(resolve,3000,'three')
})
Promise.race([p1,p2,p3]).then((resp)=>{
    console.log('then',resp)
}).catch((resp)=>{
    console.log('catch',resp)
})

运行结果

shell 复制代码
then two

race函数返回一个Promise,它将与第一个传递的promise相同的完成方式被完成。它可以是完成(resolves),也可以是失败(rejects),这要取决第一个完成的方式是两个中的哪个。

如果传的迭代是空的,则返回的 promise 将永远等待。

如果迭代包含一个或多个非承诺值和/或已解决/拒绝的承诺,则 Promise.race 将解析为迭代中找到的第一个值。

race在遇见立即执行的reject时并没有像any一样继续等待resolve的返回,而是直接返回了reject的内容。

3.4 Promise.any()

Promise.any()接收一个由Promise所组成的可迭代iterable对象,该方法会返回一个新的promise,一旦迭代对象内的任意一个promise变成了兑现状态,那么由该方法所有返回的promise就会变成兑现状态,并且它的兑现值就是可迭代对象内的首先兑现的promise的兑现值。

如果可迭代对象内的promise最终都没有兑现(即所有 promise 都被拒绝了),,那么该方法所返回的 promise 就会变成拒绝状态,并且它的拒因会是一个 AggregateError 实例,这是 Error 的子类,用于把单一的错误集合在一起。

js 复制代码
const p1=new Promise((resolve,reject)=>{
    setTimeout(resolve,2000,'one')
})
const p2=new Promise((resolve,reject)=>{
    setTimeout(resolve,1000,'two')
})
const p3=new Promise((resolve,reject)=>{
    setTimeout(resolve,3000,'three')
})
const p4=new Promise((resolve,reject)=>{
    reject('P4->reject')
})
Promise.race([p1,p2,p3,p4]).then((resp)=>{
    console.log('then',resp)
}).catch((resp)=>{
    console.log('catch',resp)
})
复制代码
tren,two

只要参数实例有一个变成fulfilled状态,包装实例就会变成fulfilled状态;如果所有参数实例都变成rejected状态,包装实例就会变成rejected状态。

Promise.any()Promise.race()方法很像,只有一点不同,就是Promise.any()不会因为某个Promise变成rejected状态而结束,必须等到所有参数Promise变成rejected状态才会结束。

3.5 Promise.all()

Promise.all()方法接收一个 Promise的iterable类型的输入。并且只返回一个Promise实例,那个输入的所有promise的resolve回调的结果是一个数组。

Promise的resolve回调执行是在所有输入的promise的resolve回调都结束,或者输入的iterable里没有promise了的时候。

它的reject回调执行时,只要任何一个输入的promise的reject回调执行或者执行或者输入不合格的promise就会立即抛出错误,并且reject的是第一个抛出的错误信息。

javascript 复制代码
var p1 = new Promise((resolve, reject) => {
  setTimeout(resolve, 1000, 'p1->one');
});
var p2 = new Promise((resolve, reject) => {
  setTimeout(resolve, 2000, 'p2->two');
});
var p3 = new Promise((resolve, reject) => {
  setTimeout(resolve, 3000, 'p3->three');
});
var p4 = new Promise((resolve, reject) => {
  setTimeout(resolve, 4000, 'p4->four');
});
var p5 = new Promise((resolve, reject) => {
  reject('reject');
});

Promise.all([p1, p2, p3, p4, p5]).then(values => {
  console.log(values);
}, reason => {
  console.log(reason)
});
shell 复制代码
then ['p1->one','p2->two','p3->three','p4->four']

Promise.all()主要应用需要所有异步任务都同时进行并且完成时可以使用all方法。

3.6 Promise.allSettled()

Promise.allSettled()方法返回一个在所有给定的promise都已经fulfilled或rejected后的pronise,并带有一个对象数组,每个对象表示对应的promise结果。

当您有多个彼此不依赖的异步任务成功完成时,或者您总是想知道每个promise的结果时,通常使用它。

相比之下,Promise.all()更适合彼此相互依赖或者在其中任何一个reject时立即结束。

javascript 复制代码
var p1 = new Promise((resolve, reject) => {
  setTimeout(resolve, 4000, 'p1->one');
});
var p2 = new Promise((resolve, reject) => {
  setTimeout(resolve, 3000, 'p2->two');
});
var p3 = new Promise((resolve, reject) => {
  setTimeout(resolve, 2000, 'p3->three');
});
var p4 = new Promise((resolve, reject) => {
  setTimeout(resolve, 1000, 'p3->four');
});
var p5 = new Promise((resolve, reject) => {
  reject('p5->reject');
});

Promise.allSettled([p1, p2, p3, p4, p5]).then(values => {
  console.log(values);
}, reason => {
  console.log(reason)
});
shell 复制代码
then [{status:'fulfilled',value:'p1->one'},
      {status:'fulfilled',value:'p2->two'},
      {status:'fulfilled',value:'p3->three'},
      {status:'fulfilled',value:'p4->four'},
      {status:'rejected',value:'p5->reject'}]

一旦所指定的 promises 集合中每一个 promise 已经完成,无论是成功的达成或被拒绝,未决议的 Promise将被异步完成。那时,所返回的 promise 的处理器将传入一个数组作为输入,该数组包含原始 promises 集中每个 promise 的结果。

对于每个结果对象,都有一个 status 字符串。如果它的值为 fulfilled,则结果对象上存在一个 value 。如果值为 rejected,则存在一个 reason 。value(或 reason )反映了每个 promise 决议(或拒绝)的值。

可以发现和all相比,allSettled在其中一个promise返回错误时还可以继续等待结果。并且不管内部的计时器定时多少毫秒,它都会等所有结果返回后按照传参传入的顺序返回promise结果。

四、总结

根据不同场景选择 Promise.all、Promise.race、Promise.allSettled 和 Promise.any 四个方法合适的使用。

相关推荐
WeiXiao_Hyy29 分钟前
成为 Top 1% 的工程师
java·开发语言·javascript·经验分享·后端
吃杠碰小鸡1 小时前
高中数学-数列-导数证明
前端·数学·算法
kingwebo'sZone1 小时前
C#使用Aspose.Words把 word转成图片
前端·c#·word
xjt_09011 小时前
基于 Vue 3 构建企业级 Web Components 组件库
前端·javascript·vue.js
我是伪码农1 小时前
Vue 2.3
前端·javascript·vue.js
夜郎king2 小时前
HTML5 SVG 实现日出日落动画与实时天气可视化
前端·html5·svg 日出日落
辰风沐阳2 小时前
JavaScript 的宏任务和微任务
javascript
夏幻灵3 小时前
HTML5里最常用的十大标签
前端·html·html5
冰暮流星3 小时前
javascript之二重循环练习
开发语言·javascript·数据库
Mr Xu_3 小时前
Vue 3 中 watch 的使用详解:监听响应式数据变化的利器
前端·javascript·vue.js