1、介绍
Promise 译为承诺,是异步编程的一种解决方案,比传统Promise的解决方案(回调函数)更加合理和更加强大在以往我们如果处理多层异步操作,我们往往会像下面那样编写我们的代码
doSomething(function (result) { doSomethingElse(result, function (newResult) { doThirdThing(newResult, function (finalResult) { console.log("得到最终结果:" + finalResult); }, failureCallback); }, failureCallback); }, failureCallback);
阅读上面代码,是不是很难受,上述形成了经典的回调地狱现在通过Promise的改写上面的代码
doSomething().then(function (result) { return doSomethingElse(result) }).then(function (newResult) { return doThirdThing(newResult) }).then(function (finalResult) { console.log("得到最终结果:" + finalResult); }).catch(failureCallback)
瞬间感受到解决异步操作的优点promise 链式操作减低了编码难度代码可读性明显增强 下面我们正式来认识promise:
状态:
promise对象仅有三种状态
-
pending (进行中)
-
fulfilled (已成功)
-
rejected(已失败)
特点:
-
对象的状态不受外界影响,只有异步操作的结果,可以决定当前是哪一种状态
-
一旦状态改变(从 pending 变为 fulfilled 和从pending 变为 rejected ),就不会再变,任何时候都可以得到这个结果
2、用法
Promise对象是一个构造函数,用来生成Promise实例
let promise=new Promise(function(resolve,reject){})
Promise构造函数接受一个函数作为参数,该函数的两个参数分别是resolve 和 reject
resolve 函数的作用是,将Promise 对象的状态从"未完成"变为成功” reject 函数的作用是,将 Promise 对象的状态从“未完成”变为“失败”
实例方法
构建出来的实例存在以下方法Promise
-
then()
-
catch()
-
finally()
#then() then是实例状态发生改变时的回调函数,第一个参数是resolved 状态的回调函数,第二个参数是 rejected 状态的回调函数 then 方法返回的是一个新的 Promise 实例,也就是promise能链式书写的原因
getJSON("/data.json").then(function(){ return json.post }).then(function(){ //... })
#catch()
catch()方法是 .then(null,rejection)或 .then(undefined,rejection)的别名,用于指定发生错误时的回调函数
getJSON("/data.json").then(function(result){ // ... }).catch(function(err){ //处理getJSON 和 前一个回调函数运行时发生的错误 console.log("错误",err) })
Promise 对象的错误具有“冒泡”性质,会一直向后传递,直到被捕获为止
getJSON("/post/1.json").then(function(post){ return getJSON(post.commentURL); }).then(function(comments){ //... }).catch(function(err){ //处理前面三个Promise产生的错误 })
一般来说,使用 catch 方法代替 then()第二个参数Promise 对象抛出的错误不会传递到外层代码,即不会有任何反应
const someAsyncThing=function(){ return new Promise(function(resolve,reject){ //下面一行会报错,因为x没有声明 resolve(x+2) }) }
浏览器运行到这一行,会打印出错误提示 ReferenceError:x is not defined,但是不会退出进程 catch()方法之中,还能再抛出错误,通过后面 catch 方法捕获到
#finally()
finally()方法用于指定不管Promise对象最后状态如何都会执行的操作
promise .then(result=>{...}) .catch(error=>{...}) .finally(()=>{...})
Promise构造函数方法
-
Promise构造函数存在以下方法: Promise.all()
-
Promise.race()
-
Promise.allSettled()
-
Promise.resolve()
-
Promise.reject()
-
Promise.try()
all()
Promise.all()方法用于将多个Promise实例,包装成个新的 Promise实例
const p=Promise.all([p1,p2,p3])
接受一个数组(选代对象)作为参数,数组成员都应为Promise 实例 实例p的状态由 p1、p2、 p3 决定,分为两种:
-
只 有p1、p2、p3的状态都变成 fulfilled ,p的状态才会变成 fulfilled ,此时 p1、p2、p3的返回值组成一个数组,传递给p的回调函数
-
只要 p1、p2、p3之中有一个被 rejected,p的状态就变成rejected,此时第一个被 reject 的实例的返回值,会传递给 p的回调函数
注意,如果作为参数的Promise实例,自己定义了catch方法,那么它一旦被 rejected,并不会触发Promise.all()的 catch 方法
const p1=new Promise((resolve,reject)=>{ resolve("hello"); }) .then(result=>result) .catch(err=>err);
如果 p2 没有自己的 catch 万法,就会调用 Promise.all()的 catch 方法
race()
Promise.race()万法同样是将多个Promise 实例,包装成个新的Promise实例
const p=Promise.race([p1,p2,p3]);
只要 p1、p2、p3之中有一个实例率先改变状态状态就跟着改变 率先改变的Promise实例的返回值则传递给p的回调函数
alISettled() Promise.allsettled() 方法接受一组 Promise 实例作为参数,包装成一个新的Promise实例
只有等到所有这些参数实例都返回结果,不管是 fulflled包装实例才会结束不是 rejected,
resolve() 将现有对象转为Promise 对象
Promise.resolve("foo") //等价于 new Promise(resolve=>resolve("foo"))
参数可以分成四种情况,分别如下
-
参数是一个Promise实例,promise.resolve 将不做任何修改、原封不动地返回这个实例
-
参数是一个 thenable 对象,promise.resolve 会将这个对象转为Promise对象,然后就立即执行thenable 对象的 then()方法
-
参数不是具有 then()方法的对象,或根本就不是对象,Promise.resolve()会返回一个新的Promise 对象,状态为 resolved
-
没有参数时,直接返回一个resolved 状态的Promise对象
reject() Promise.reject(reason)万法也会返回一个新的 Promise实例,该实例的状态为 rejected
const p=Promise.reject("出错了"); //等同于 const p=new Promise((resolve,reject)=>reject("出错了"))
Promise.reject()方法的参数,会原封不动地变成后续方法的参数
Promise.reject("出错了") .catch(err=>{ console.log(e==="出错了") }) //true