Promise
作用:主要是来解决Ajax的异步问题
传统方式:回调函数来解决异步问题,类似如下问题
ajax(url, {
// 成功后回调
ajax(url, {
// 成功之后再回调
ajax(url, {
// 成功之后再回调
})
})
})
注意:一般情况下,如果请求成功,执行某个函数,看着比较混乱,一个回调还比较容易分清,如果是多个回调的话,代码易读性可想而知
Promise 两个特点
1、对象的状态不受外界影响。Promise 对象代表一个异步操作,有三种状态:
- pending: 初始状态,不是成功或失败状态。
- fulfilled: 意味着操作成功完成。
- rejected: 意味着操作失败。
2、一旦状态改变,就不会再变,任何时候都可以得到这个结果。Promise 对象的状态改变,只有两种可能:从 Pending 变为 Resolved 和从 Pending 变为 Rejected。只要这两种情况发生,状态就凝固了,不会再变了,会一直保持这个结果。就算改变已经发生了,你再对 Promise 对象添加回调函数,也会立即得到这个结果。这与事件(Event)完全不同,事件的特点是,如果你错过了它,再去监听,是得不到结果的。
优缺点
优点: 有了 Promise 对象,就可以将异步操作以同步操作的流程表达出来,避免了层层嵌套的回调函数。此外,Promise 对象提供统一的接口,使得控制异步操作更加容易。
缺点: Promise 也有一些缺点。首先,无法取消 Promise,一旦新建它就会立即执行,无法中途取消。其次,如果不设置回调函数,Promise 内部抛出的错误,不会反应到外部。第三,当处于 Pending 状态时,无法得知目前进展到哪一个阶段(刚刚开始还是即将完成)。
如何使用
1. 如何创建一个 promise,参数详解
let promise = new Promise(function(resolve, reject) {
//当异步代码执行成功时,我们才会调用resolve(...), 当异步代码失败时就会调用reject(...)
//在本例中,我们使用setTimeout(...)来模拟异步代码,实际编码时可能是XHR请求或是HTML5的一些API方法.
setTimeout(function(){
resolve("成功!"); //代码正常执行!
}, 250);
});
方法一:
promise.then(success, fail)
// success 请求成功执行的内容
// fail 请求失败执行的内容
Eg:
promise.then(function(data){
//data的值是上面调用resolve(...)方法传入的值.
//data参数不一定非要是字符串类型,这里只是举个例子
console.log(data)
}, fail)
方法二:
promise.then(res=>{}).catch(err=>{})
// then 请求成功后执行内容
// catch 请求失败后执行内容
// 上边的这两种都可以使用,不过后者用的较为普遍
2. promise 简单使用
let a = 'hello'
let promise = new Promise(function(resolve, reject) {
if (a === 'hello') {
resolve('success')
} else {
reject('error')
}
});
// 方法一
promise.then(res => {
console.log(res) // 如果 a === 'hello' 也就是 resolve 的情况下,就会打印 'success'
},err => {
console.log(err) // 如果 a !== 'hello' 也就是 reject 的情况下就会打印 'error'
})
// 方法二
promise.then(res => {
console.log(res) // resolve 的情况下,就会走到这里
}).catch(err => {
console.log(err) // reject 的情况下,会捕获到错误内容
})
3. promise.resolve() 和 promise.reject()
Promise.resolve('a') 将括号中的内容,转为一个promise 对象,并且是resolve (成功) 状态
// 等价于
new Promise(resolve => {
resolve('a')
})
Promise.reject('a') 将括号中的内容,转为一个promise 对象,并且是reject (失败) 状态
// 等价于
new Promise(reject => {
resolve('a')
})
4. promise.all()
概念:Promise.all(ajax1, ajax2, ajax3)
方法返回一个 Promise 实例
此实例在参数内所有的 promise
都 请求成功(resolve) 或参数中不包含 promise
时回调完成(resolve)
如果参数中 promise
有一个失败(rejected),此实例回调失败(reject),失败原因会返回第一个失败 promise
的结果。
自我理解:
let promise = promise.all(ajax1, ajax2, ajax3)
promise 相当于把ajax1, ajax2, ajax3
打包,返回一个 promise 对象,只有三个全部成功时,promise 才会返回成功状态
如果其中一个请求失败了,promise 会直接返回失败,失败内容就为第一个请求失败的返回内容
var promise1 = Promise.resolve(3);
var promise2 = 42;
var promise3 = new Promise(function(resolve, reject) {
setTimeout(resolve, 100, 'foo');
});
Promise.all([promise1, promise2, promise3]).then(function(values) {
console.log(values);
});
// expected output: Array [3, 42, "foo"]
5. promise.race()
Promise.race(iterable)
方法返回一个 promise,一旦迭代器中的某个promise解决或拒绝,返回的 promise就会解决或拒绝。
自我理解:参数中可传入多个promise,只要其中一个完成(resolve, reject都算),直接返回
var promise1 = new Promise(function(resolve, reject) {
setTimeout(resolve, 200, 'one');
});
var promise2 = new Promise(function(resolve, reject) {
setTimeout(resolve, 100, 'two');
});
Promise.race([promise1, promise2]).then(function(value) {
console.log(value);
// 虽然两个都返回resolve的结果,但是promise2 返回的更快一些,所以输出的是promise2 的内容
});
6: 真实场景模拟
var promise1 = new Promise(function(resolve, reject) {
$.ajax({
type: 'POST/GET',
url: '/jhbar/bar?appkey=key', // 随便写的url,
success:function(data){
resolve(data)
}
error:function(data){
reject(data)
}
});
var promise2 = new Promise(function(resolve, reject) {
$.ajax({
type: 'POST/GET',
url: '/jhbar/bar?appkey=key', // 随便写的url,
success:function(data){
resolve(data)
}
error:function(data){
reject(data)
}
});
Promise.all([promise1, promise2]).then(function(value) {
// 当所有的都请求成功了 就会走这里
// 此时两个的数据都拿到了,但是只有一个value,所以需要解构一下
let [data1, data2] = value
// data1就是promise1 中返回的数据
// data2就是promise2 中返回的数据
}).catch(function(err) {
// 当其中一个 reject ,就会走这里 , 输出的错误原因是第一个被拒绝的原因
console.log(err)
})
本文是个人的理解和总结,如有不妥,请赐教