我们 学习一个新的特性时,我习惯先了解他是什么, 有什么用
在 w3c中 可知 Promise 是 抽象异步处理对象以及对其进行各种操作的组件 . 他 多用于 处理回调地狱 . 什么是回调地狱呢? 即 嵌套多个回调 如果 有多个回调互相嵌套 则 会难以调试与 理解 增大代码维护的难度与可读性
使用 promise 就能解决这个问题 , promise 可以是一个占位符,表示异步操作的执行结果, 函数可以返回一个promise 而不 是 传递一个回调
promise 都会有一个 短暂的生命周期
有两种状态
初始的挂起未决状态 --> 异步未结束
已决的状态 ---> 异步操作结束
处于 已决转态 会有两种情况
1 已经成功完成的异步操作
2 可能是一个错误或者其他的原因导致了 异步的操作没成功
此时 promise中有个 [ [PromiseState]] 属性 会被设置 为 pending fulfilled 或者 rejected , 以反映 promise 的状态处于 哪一步 . 但这个属性 并不在 promise 对象上面 暴露. 因此 无法 判断 他处于那种状态
但此时其 提供了
then() 方法
他在所有的promise 上都存在. 并且接受两个参数 .
第一个 参数 是promise 被完成时 调用的 函数 , 异步操作的结果数据
都会传入 完成函数
第二个函数 则是 promise 被拒绝的时调用的函数, 也会将失败的参数数据
这两个参数是可选的 可以自由的监听 完成 和失败的处理函数
catch 方法
Promise有catch()方法,等同于只传递拒绝处理函数给then()方法:
用处
比如 Vue 发起axios 的请求时 正常来说异步 返回的是 一个 回调函数. 但此时 使用 promise 直接返回一个 axios.get或者 axios.post 让这个 promise 对象 (axios是promise对象 )自己 进行 成功 ( .then() ) 之后的 处理 或者失败(.catch() ) 的提示
他人总结:
Promise 具有三种状态:挂起、已完成、已拒绝。一个 Promise 起始于挂起态,并在成功时转为完成态,或在失败时转为拒绝态。 then() 方法允许你绑定完成处理函数与拒绝处理函数,而 catch() 方法则只允许你绑定拒绝处理函数;
能够将多个Promise串联起来组成Promise链,并且能够在中间传递值,甚至是传递Promise对象。 then() 的调用都创建并返回了一个新的 Promise ,只有在前一个 Promise 被决议过,新 Promise 也会被决议。 同时也可以使用Promise.all()和Promise.race()方法来管理多个Promise
例子
/**
* promise 对象是一个构造函数, 用来生成 promise 对象
*
* resolve 将 promise 对象的状态从 未完成=> 转变成 成功, 并且在 异步调用成功之后, 将成功之后的结果 传递出去
* reject 将 promise 对象的状态 从 未完成=> 转变成 失败, 并且在 异步调用失败的错误作为参数 传递出去
*
* promise 实例生成之后 可以分别指定 resolve 状态和 reject 状态的 回调函数
*/
// promise
var promise = new Promise((resolve, reject) => {
if (true) {
resolve();
} else {
reject();
}
})
// 例子 一
function timeFun (ms) {
return new Promise ((resolve, reject) => {
setTimeout(resolve, ms, 'done');
})
}
timeFun(100).then(resolve => {
console.log(resolve) // done
})
// 例子二 // promise 一旦建立就会立即执行
const promiseTwo = new Promise((resolve, reject) => {
console.log("我是第一个输出的");
resolve();
})
promiseTwo.then(res => {
console.log('我是第三个输出的');
})
console.log('我是第二个输出的')
/**
* 输出结果
* promise.js:31 我是第一个输出的
promise.js:39 我是第二个输出的
promise.js:36 我是第三个输出的
promise.js:26 done
promise 新建之后会立即执行 , 首先输出第一 , promise 里面的 resolve 是异步方法, 所以先执行 所有同步再执行异步, 此时 会先输出 第二,
然后再输出 第三 , 100 之后 会再执行 done
*/
// 例子三 promise 实现操作 Ajax 操作
let promiseAjax = function (url) {
let promise = new Promise ((resolve, reject) => {
// 新建一个 对象
var xhr = new XMLHttpRequest();
// 请求方式
xhr.open('GET', url);
// 状态请求改变的回调
xhr.onreadystatechange = handler;
// 返回数据格式
xhr.responseType = 'json',
xhr.setRequestHeader('Accept', 'application/json');
xhr.send();
function handler() {
if (this.status === 200) {
resolve(this.response);
} else {
reject(new Error(this.statusText))
}
}
})
return promise
}
var url = 'http://httpbin.org/get';
promiseAjax(url).then(res => {
console.log('res', res)
}).catch(error => {
console.log('error',error)
})
// 输出 res null promise 中的 resolve 跟 reject 都 会带有参数回传 ,
//一个成功之后的参数, 一个失败之后的, 成功的也可能是 一个 promise 实例, 如 Vue 中的 axios 实例
/**
* 要理解 promise 中的 then 方法, 该方法作用是在 Promise 实例状态改变时的回调函数 , then 方法的第一个参数 是 resolve(成功的) 状态的回调,
* 第二个参数 是 reject(失败的) 的 状态的回调
* {
* 但是不推荐使用第二个参数-> 推荐使用 catch 进行捕获错误, 原因-> 因为promise的 状态一旦改变,就永久保持该状态, 使用 then 第二个参数识别错误,错误并不会一直传递,
* 但Promise对象的错误具有传递性质,它会一直往下传递,直到被catch捕获到为止。
* },
* 还有需要注意的是 then 方法返回的 还是一个 promise 对象.
* 所以我们可以使用 链式 写法, then 后面再跟 then 方法 (vue 的 axios 使用)
*
* 如下
*
*/
// then 链式写法
promiseAjax(url).then(res => {
console.log(1,res)
return res
}).then(val => {
console.log(2, val) // 返回的是 与上面一直的结果 输出: 1 null 2 null
})
// 错误捕获案例
// 不推荐 的写法
var p6 = new Promise((resolve, reject) => { });
p6.then((data) => {
// success
}, (error)=>{
// error
});
// 推荐 的写法
p6.then((data) => {
// success
}).catch((error) => {
// error
})
这篇文章解析的更为 详细易懂.
https://www.jianshu.com/p/063f7e490e9a