前言
大家好,我是HoMeTown
,Promise想必大家都知道,在平时的开发工程中也经常会有用到,但是Promise作为ES6的重要特性,其实还拥有很多丰富的知识,本文面向比较初级一些的同学,可以帮你搞懂Promise到底做了什么,顺便起到一个备忘录的作用。
Promise?
Promsie中文直译承诺
,其实也很好理解,就是无论这个异步任务最后的结果怎么样,我承诺会给你一个结果。
Promise在JavaScript中是一个处理异步代码的解决方案,他的出现解决了JavaScript异步编程回调地狱的问题(此处 que一下wxapi)。
Promise对象代表一个异步操作,有三种状态:pending(进行中)
fulfilled(已成功)
rejected(已失败)
。
一个Promsie实例必然处于上述的三个状态直译。
Promise的运行机制
当Promise被实例化后,其实例会处于pending
状态,一般情况下,遇到以下操作,Promise的状态会被改变:
- 执行
resolve
- 执行
reject
- 出现报错
下面举个例子:
const p1 = new Promise((resolve, reject) => { resolve('成功') console.log('这里还能执行吗? -- p1') reject('失败') console.log('这里呢? -- p1') }) console.log(p1,'p1') const p2 = new Promise((resolve, reject) => { reject('失败') resolve('成功') console.log('这里还能执行吗? -- p2') }) console.log(p2, 'p2') const p3 = new Promise((resolve, reject) => {}) console.log(p3, 'p3') const p4 = new Promise((resovle, reject) => { throw 'error' }) console.log(p4, 'p4') const p5 = new Promise((resovle, reject) => { throw 'error' resolve('成功') reject('失败') }) console.log(p5, 'p5') const p6 = new Promise('测试') console.log(p6, 'p6') 复制代码
执行结果如下:
通过上图中的执行结果我们可以发现:
- new Promise 返回了一个Promise实例
- 传入Promise构造函数中的执行函数,会被立即执行,且拥有了两个参数
resolve
reject
resolve操作
之后 PromiseState(状态) 会变成flufilled
, PromiseResult 为resolve的参数
reject操作
之后 PromiseState(状态) 会变成rejected
,PromiseResult 为rejected的参数
报错
之后 之后 PromiseState(状态) 会变成rejected
,PromiseResult 为报错信息
- 如果没有执行
resolve/reject
,也没有出现报错
,PromiseState(状态) 会保持pending
,PromiseResult 为undefined
- 一旦执行
resolve/reject
,或者出现报错
,Promise
会修改Promise实例的PromiseState & PromiseResult
,后续的代码还会继续执行
Promise的使用
Promise作为一个构造函数可以被new
关键字进行实例化,并在.then
与 .catch
分别取到成功和失败的结果。
p1.then(res => { console.log(res, '成功')}).catch(err => {console.log('失败', err)}) 复制代码
Promise封装请求器
function request({ method = "GET", url = "", data = {}, timeout = 10000 }) { const xhr = new XMLHttpRequest(); return new Promise((resolve, reject) => { xhr.onreadystatechange = function () { if (xhr.readyState !== 4) return reject("xhr readyState error"); if (xhr.timeout > timeout) return reject("request timout"); if (xhr.status === 200) { resolve(JSON.parse(xhr.responseText)); } else { reject(xhr.statusText); } }; xhr.open(method, url); xhr.send(data); }); } 复制代码
测试请求器:
// 测试请求器 request({ method: "GET", url: "https://api.apiopen.top/api/getHaoKanVideo?page=0&size=2", }).then((res) => { console.log(res, "获取数据成功"); }); 复制代码
结果如下:
Promise原型上的方法
Promise.prototype.then
Promise.prototype具有then
方法,也就是说,每一个Promsie实例对象都可以调用then
方法得到Promsie成功的结果。
then
方法的第一个参数是flufilled
状态的回调函数,第二个参数是rejected
状态的回调函数,举个栗子:
const p1 = new Promise((resolve, reject) => { setTimeout(() => { resolve('good') reject('bad'); // 这里不会被执行 }, 1000); }); p1.then( (res) => { console.log(res, "成功"); }, (err) => { console.log(err, "失败"); } ); 复制代码
执行结果如下:
Promise.prototype.catch
catch()
方法返回一个Promise
,用捕捉指定错误并且处理错误。它的行为与调用Promise.prototype.then(_, onRejected)
相同,举个栗子:
const p1 = new Promise((resolve, reject) => { setTimeout(() => { reject("bad"); }, 1000); }); p1.catch(err => { console.log(err) }) 复制代码
执行结果如下:
then链
有趣的是,then方法也返回了一个Promsie实例,那就意味着,可以继续执行.then进行下一次的结果获取,像这样:
const p1 = new Promise((resolve, reject) => { setTimeout(() => { resolve("good"); reject("bad"); }, 1000); }); p1.then((res) => { console.log(res, "then1"); }).then(res => { console.log(res, 'then2') // undefined 'then2' }) 复制代码
在then
方法中,你可以通过return
决定下一次的结果是什么:
- 返回基本数据类型或者引用数据类型,下一次接受该数据,状态为
flufilled
,可继续.then
- 返回一个
Promsie
- 状态为
flufilled
,可继续执行.then
- 状态为
pending
,不会继续执行.then
,直到当前Promise实例得到一个有效的状态 - 状态为
rejected
,不会继续执行.then
,直接走到.catch
- 什么都没返回,执行
.then
,结果为undefined
- 出现报错,直接走到
.catch
Promise.prototype.finally
finally
方法用于不管结果如何,都会执行的操作,可以避免相同的逻辑在then
&catch
重复写的情况,举个栗子:
const p1 = new Promise((resolve, reject) => { setTimeout(() => { reject("bad"); }, 1000); }); p1.then((res) => { console.log(res, "成功"); }) .catch((err) => { console.log(err, "失败"); }) .finally(() => { console.log("不管成功不成功"); }); 复制代码
执行结果如下:
Promise构造函数上的方法
Promise的prototype上也有一些函数可以使用,比如(race、all、any、race等):
Promise.resolve
Promise.resolve方法不是excutefunc上的resovle方法,而是原型上的方法,该方法接受一个参数,返回一个状态为fulfilled 的 Promise实例
,如果参数为基本类型或者引用类型,则PromiseResult
为传递进来的参数,举个栗子
const pstring = Promise.resolve('HoMeTowm') console.log(pstring,'字符串 Promise实例') const pnumber = Promise.resolve(123) console.log(pnumber,'数字 Promise实例') const pboolean = Promise.resolve(true) console.log(pboolean,'布尔值 Promise实例') const pobject = Promise.resolve({name: 'HoMeTowm'}) console.log(pobject,'对象 Promise实例') console.log('......') 复制代码
执行结果如下: