Promise对象
promise对象是什么
ECMAScript 6新增了Promise对象,该对象允许对延迟和异步操作流程进行控制。一个Promise对象就是一个代表了异步操作最终完成或者失败的对象
开发人员可以使用由其他函数创建并返回的Promise对象。Promise对象本质上就是一个绑定回调的对象,而不是将回调传入函数内部。
一个Promise有以下几种状态:
- pending:初始状态,既不是成功,也不是失败状态。
- fulfilled:意味着操作成功完成。
- rejected:意味着操作失败。
创建Promise对象
ECMAScript 6 新增了Promise对象是一个构造函数,用于创建生成Promise对象实例
new Promise(function(resolve,reject){})
当前的构造函数Promise接收一个回调函数
- resolve–是一个函数,将Promise的状态改为fulfilled(完成)
- reject–是一个函数,将Promise的状态改为rejected(失败)
//Promise的初始化状态--既不成功,也不失败
let promise = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('测试成功了')
}, 200)
})
//将Promise状态改变--要么成功,要么失败
promise.then((value) => {
console.log(value) //测试成功了
})
Promise对象经常由其他函数创建并返回
function fn() {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve('测试成功了')
}, 200)
})
}
var promise = fn();
Promise对象的约定
在应用Promise时,将会有一下约定
- 在JavaScript事件队列的当前运行完成之前,回调函数永远不会被调用。
- 通过 .then形式添加的回调函数,甚至都在异步操作完成之后才被添加的函数,都会被调用。
- 通过多次调用.then,可以添加多个回调函数,他们会按照插入顺序并且独立运行。
因此Promise最直接的好处就是链式调用.
Promise对象的链式操作
常见的需求就是连续执行两个或者多个异步操作。这种情况下,每一个后来的操作都在前面的操作执行成功之后,带着上一步操作所返回的结果开始执行。可以通过创建一个Promise来完成这种需求。then()函数会返回一个新的Promise,跟原来的不同
基本上,每一个Promise代表了链式中另一个异步过程的完成。
下面测试一下then()方法每返回一个Promise对象都是一个新的Promise对象
//创建Promise对象
let promise = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('测试成功了')
}, 200)
})
// then()方法返回了一个新的Promise对象
let promise2 = promise.then((value) => {
console.log(value)
})
// promise和promise2是两个Promise对象
console.log(promise === promise2)
Promise对象原型方法
then()方法
then()方法用于为Promise对象添加状态改变时回调函数。then()方法的第一个参数是resolved状态的回调函数,第二个参数(可选)是rejected状态的回调函数
- 第一个回调函数:当Promise变成接受状态(fulfillment)时,该参数作为回调函数被调用。该函数有一个参数,即接受的最终结果
- 第二个回调函数:当Promise变成拒绝状态(rejection)时,该参数作为回调函数被调用。该函数有一个参数,即拒绝的原因
catch()方法
catch()方法返回一个Promise对象,并且处理拒绝的情况。他的行为与调用then()方法相同。
- 回调函数:当Promise被rejected时,被调用该回调函数。该函数具有一个参数,即rejection的原因
finally()方法
finally()方法返回一个Promise对象,在执行then()和catch()后,都会执行 finally 指定的回调函数。避免同样的语句需要在then()和catch()中各写一次的情况。
- 回调函数:Promise状态改变后的回调函数
//创建Promise对象
let promise = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('测试成功了')
}, 200)
})
//then()方法--改变Promise状态时执行回调函数(成功)
promise.then((value) => {
console.log('then()方法:' + value) //then()方法:测试成功了
}).catch((value) => {
console.log('catch()方法:' + value)
}).finally(() => {
console.log('finally') //finally
})
Promise对象的方法
Promise.all()方法
Promise.all()方法用于将多个Promise对象,包装成一个新的Promise对象。
- iterable:一个可迭代对象,如Array或String等
let promise1 = new Promise(() => {})
let promise2 = new Promise(() => {})
let promise3 = new Promise(() => {})
//Promise.all()方法将多个Promise对象整合成一个Promise对象
let promise = Promise.all([promise1, promise2, promise3])
console.log(promise) //Promise { <pending> }
Promise.race()方法
Promise.race()方法返回一个Promise对象,一旦迭代器中的某个Promise解决或拒绝,返回的Promise就会解决或拒绝
Promise.race()方法以最快返回的Promise对象进行输出。
let promise1 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('one')
}, 300)
})
let promise2 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('two')
}, 100)
})
let promise3 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('three')
}, 200)
})
// Promise.all() 是以所有Promise对象的状态都改变时, 表示整合后的Promise对象成功或者失败
promise.then((value) => {
console.log(value) //[ 'one', 'two', 'three' ]
})
//race()方法--是以某个Promise对象的状态改变时,表示整合后的Promise对象成功或失败
Promise.race([promise1, promise2]).then((value) => {
console.log(value) //two
})
加载图片
可以将图片的加载写成一个Promise,一旦加载完成,Promise的状态就会发生变化
const preloadImage = function(path) {
return new Promise(function(resolve, reject) {
const image = new Image();
image.onload = resolve;
image.onerror = reject;
image.src = path
})
}
通过Ajax加载图片
//通过Ajax加载图片
function imgLoad(url) {
return new Promise(function(resolve, reject) {
var request = new XMLHttpRequest();
request.open('GET', url)
request.onload = function() {
if (request.status === 200) {
resolve(request.response)
} else {
reject(Error('error code:' + request.statusText))
}
}
request.onerror = function() {
reject(Err('It is a network error'))
}
request.send()
})
}
Promise执行流程
为了解决回调函数的致命问题–回调陷阱(地狱),我们可以通过Promise来解决
function fn(fn1) {
return new Promise(() => {})
}
let promise = fn()
promise.then().then()