【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 四个方法合适的使用。

相关推荐
拉不动的猪8 分钟前
前端常见数组分析
前端·javascript·面试
小吕学编程24 分钟前
ES练习册
java·前端·elasticsearch
Asthenia041232 分钟前
Netty编解码器详解与实战
前端
袁煦丞36 分钟前
每天省2小时!这个网盘神器让我告别云存储混乱(附内网穿透神操作)
前端·程序员·远程工作
一个专注写代码的程序媛2 小时前
vue组件间通信
前端·javascript·vue.js
一笑code2 小时前
美团社招一面
前端·javascript·vue.js
懒懒是个程序员2 小时前
layui时间范围
前端·javascript·layui
NoneCoder2 小时前
HTML响应式网页设计与跨平台适配
前端·html
凯哥19702 小时前
在 Uni-app 做的后台中使用 Howler.js 实现强大的音频播放功能
前端
烛阴2 小时前
面试必考!一招教你区分JavaScript静态函数和普通函数,快收藏!
前端·javascript