【ES6.0】- Promise对象

简介: 笔记

一、概述


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


二、Promise状态


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


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


Promise状态演示

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对象,因此可以采用链式写法:

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)
})

输出结果

resolve-01
resolve-01-02
resolve-01-02-03

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


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

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)
})

输出结果:

输入值<100,传入值为:50
输入值<100,传入值为:82


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


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

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

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)时得到结果。它的语法如下:

Promise.race([promise1,promise2,..])

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

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)
})

运行结果

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 的子类,用于把单一的错误集合在一起。

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的是第一个抛出的错误信息。

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)
});
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时立即结束。

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

目录
相关文章
|
6月前
|
JSON 前端开发 JavaScript
ES6类的使用和定义.Json.Promise对象的使用
ES6类的使用和定义.Json.Promise对象的使用
58 0
|
前端开发 Go
15 # promise 延迟对象的作用
15 # promise 延迟对象的作用
64 0
|
4月前
|
前端开发 安全
协程问题之协程函数返回的Promise对象必须满足哪些要求
协程问题之协程函数返回的Promise对象必须满足哪些要求
|
4月前
|
前端开发 JavaScript
ES6 中 Promise对象使用学习
ES6 中 Promise对象使用学习
40 1
|
6月前
|
前端开发 JavaScript API
Promise 对象与 Promises/A+ 规范
Promise 对象与 Promises/A+ 规范
94 0
|
6月前
|
前端开发 JavaScript 数据处理
JavaScript中的异步编程及Promise对象
【2月更文挑战第3天】 传统的JavaScript编程模式在处理异步任务时常常会导致回调地狱和代码可读性较差的问题,而Promise对象的引入为解决这一问题提供了一种优雅的解决方案。本文将介绍JavaScript中的异步编程方式以及Promise对象的使用方法和优势,帮助读者更好地理解和运用异步编程技术。
52 8
|
6月前
|
前端开发
用Promise对象实现的 Ajax
用Promise对象实现的 Ajax
34 0
|
前端开发 JavaScript API
ES6-ES11-第一部分-let、const、解构赋值、模板字符串、简化对象写法、箭头函数、函数参数默认值、rest 参数、扩展运算符、Symbol、迭代器、生成器、Promise、Set、Map(五)
ES6-ES11-第一部分-let、const、解构赋值、模板字符串、简化对象写法、箭头函数、函数参数默认值、rest 参数、扩展运算符、Symbol、迭代器、生成器、Promise、Set、Map(五)
|
6月前
|
前端开发 算法
2723. 两个 Promise 对象相加
2723. 两个 Promise 对象相加
42 0
|
11月前
|
前端开发
ES6学习(八)—Promise对象 超鸡重要
ES6学习(八)—Promise对象 超鸡重要