赞
踩
在异步编程中,许多操作都会放在回调函数(callback)中,有时候需要拿到上一个异步操作的返回值再做第二次请求
比如:
asyncOperation(data => {
// 处理 `data`
anotherAsync(data2 => {
// 处理 `data2`
yetAnotherAsync(() => {
// 完成
})
})
})
上面代码中,每增加一个异步请求,就会多添加一层回调函数的嵌套,过多的回调也就让我们陷入“回调地狱”,让代码变得不易阅读与维护
引入 Promises 之后的代码
promiseSomething()
.then(data => {
// 处理 `data`
return anotherAsync()
})
.then(data2 =>{
// 处理 `data2`
return yetAnotherAsync()
})
.then(() => {
// 完成
})
Promises 将嵌套的 callback,改造成一系列的.then的连缀调用,去除了层层缩进的糟糕代码风格
注意:Promise 本身不是异步,往往内部都是封装一个异步任务
Promise对象的状态改变,只有两种可能:从pending变为 fulfilled 和从pending变为rejected,一旦确定就不会再改变
Promise构造函数接受一个函数作为参数,该函数的两个参数分别是resolve和reject。它们是两个函数,由 JavaScript 引擎提供,不用自己部署
const promise = new Promise((resolve, reject) => {
if (/* 异步操作成功 */) {
//如果 true ,把容器的状态改为 resolve
resolve(value)
} else {
//如果 false ,把容器的状态改为 reject
reject(error)
}
})
resolve函数的作用是:将Promise对象的状态从“未完成”变为“成功”,在异步操作成功时调用,并将异步操作的结果,作为参数传递出去
reject函数反之
promise 内部有三个状态,分别是pending,fulfilled和rejected
pending是对象创建后的初始状态,当调用resolve
函数时变为fulfilled(成功)
状态(可调用.then
方法进行成功处理),当调用reject
函数时变为rejected (失败)
状态(可调用.catch
方法进行失败处理)
promise
.then(value => {
// 成功的回调,接收的就是容器中的 resolve 函数
// 容器中 resolve 函数传的是什么,这里接收就是什么
console.log(value)
})
.catch(error => {
// 失败的回调,接收的就是容器中的 reject 函数
console.log(error)
})
链式写法
//封装 Promise API function fzPromise(isFlag,data,err) { return new Promise((resolve, reject) => { if (isFlag) { resolve(data) } else { reject(err) } }); } const promiseOne = new fzPromise(true,1,'操作失败'); const promiseTwo = new fzPromise(true, 2, '操作失败'); const promiseThree = new fzPromise(false, 3, '操作失败'); promiseOne .then((data) => { console.log(data); //当 promiseOne 读取成功,当前函数 return 的结果就能在后面的 then 中的回调函数接收到 return promiseTwo },(err) => { console.log(err); }) //这里是 promiseTwo 的 resolve .then((data) => { console.log(data); return promiseThree },(err) => { console.log(err); }) //这里是 promiseThree 的 resolve .then((data) => { console.log(data); },(err) => { //因为 promiseThree 是 false ,所以结果是 reject 传的 '操作失败' console.log(err); }) //1 //2 //操作失败
let ajax = function(url, params, type = 'POST') { return new Promise((resolve, reject) => { $.ajax({ type, url, data: params, dataType: 'json', success(res) { resolve(res) }, error(res) { reject('响应错误') } }) }) } // 使用示例 ajax('url',{channelIds: 1}).then(res => { console.log(res) })
1.Promise.resolve()
Promise.resolve('foo')
// 等价于
new Promise(resolve => resolve('foo'))
let thenable = {
then(resolve, reject) {
resolve(42);
}
}
let p1 = Promise.resolve(thenable);
p1.then(function(value) {
console.log(value); // 42
})
2.Promise.reject()
const p = Promise.reject('出错了');
// 等同于
const p = new Promise((resolve, reject) => reject('出错了'))
p.then(null, function (s) {
console.log(s)
});
// 出错了
3.Promise.all()
用于将多个 Promise 实例,包装成一个新的 Promise 实例, 接受一个数组作为参数, 可以不是数组,但必须具有 Iterator 接口
const p = Promise.all([p1, p2, p3])
p
的状态由p1
、p2
、p3
决定,分成两种情况
p1
、p2
、p3
的状态都变成fulfilled
,p
的状态才会变成fulfilled
,此时p1
、p2
、p3
的返回值组成一个数组,传递给p
的回调函数p1
、p2
、p3
之中有一个被rejected
,p
的状态就变成rejected
,此时第一个被reject
的实例的返回值,会传递给p
的回调函数const p1 = new Promise((resolve, reject) => { resolve('hello'); }) .then(result => result) .catch(e => e); const p2 = new Promise((resolve, reject) => { throw new Error('报错了'); }) .then(result => result) .catch(e => e); Promise.all([p1, p2]) .then(result => console.log(result)) .catch(e => console.log(e)); // ["hello", Error: 报错了]
上面代码中,p1会resolved,p2首先会rejected,但是p2有自己的catch方法,该方法返回的是一个新的 Promise 实例,p2指向的实际上是这个实例。该实例执行完catch方法后,也会变成resolved,导致Promise.all()方法参数里面的两个实例都会resolved,因此会调用then方法指定的回调函数,而不会调用catch方法指定的回调函数
4.Promise.race()
同样是将多个 Promise 实例,包装成一个新的 Promise 实例, 只要p1
、p2
、p3
之中有一个实例率先改变状态,p
的状态就跟着改变。那个率先改变的 Promise 实例的返回值,就传递给p
的回调函数
const p = Promise.race([
fetch('/resource-that-may-take-a-while'),
new Promise(function (resolve, reject) {
setTimeout(() => reject(new Error('request timeout')), 5000)
})
]);
p
.then(console.log)
.catch(console.error);
上面代码中,如果 5 秒之内fetch方法无法返回结果,变量p的状态就会变为rejected,从而触发catch方法指定的回调函数
5.Promise.allSettled()
Promise.allSettled()
方法接受一组 Promise 实例作为参数,包装成一个新的 Promise 实例。只有等到所有这些参数实例都返回结果,不管是fulfilled
还是rejected
,包装实例才会结束
function MyPromise(fn) { const that = this this.status = 'padding' // 定义初始状态 this.value = '' // 定义初始值 function resolve(value) { if (that.status === 'padding') { that.status = 'resolve' that.value = value } } function reject(value) { if (that.status === 'padding') { that.status = 'reject' that.value = value } } fn(resolve, reject) } // 定义 then 方法 MyPromise.prototype.then = function(onResolve, onReject) { const that = this if (this.status === 'resolve') { onResolve(this.value) } if (this.status === 'reject') { onReject(this.value) } } new MyPromise((resolve, reject) => { // resolve('1') reject('2') }) .then(res => { console.log(res) }, err => { console.log(err) })
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。