目录
四、Promise.resolve()与Promise.reject()
六、Promise.all(iterable)与Promise.race(iterable)
Promise是一种用于处理异步操作的JavaScript对象。它代表了一个尚未完成但最终会完成的操作,并可以返回操作的结果或错误信息。Promise对象有三种状态:pending(进行中)、fulfilled(已完成)和rejected(已拒绝)。当操作完成时,Promise对象可以从pending状态转变为fulfilled状态,表示操作成功完成;或者从pending状态转变为rejected状态,表示操作失败。
使用Promise可以更好地处理异步操作,避免了回调地狱(callback hell)的问题。通过使用Promise,可以将异步操作的结果以更直观、可读性更高的方式进行处理,而不需要嵌套多层回调函数。
说到的地狱回调又是什么呢?用一个例子来看看吧。
// 假设有三个异步操作:operation1、operation2、operation3
//地狱回调就是这样子~
operation1(function(result1) {
operation2(result1, function(result2) {
operation3(result2, function(result3) {
// 处理最终结果
});
});
});
//使用Promise写法:
operation1()
.then(result1 => {
// 在第一个操作完成后执行第二个操作
return operation2(result1);
})
.then(result2 => {
// 在第二个操作完成后执行第三个操作
return operation3(result2);
})
.then(result3 => {
// 所有操作完成后的处理
console.log(result3);
})
.catch(error => {
// 错误处理
console.error(error);
});
//你觉得哪一种写法的可读性更好?后期更好维护呢?
Promise通过new Promise()将构造函数实例化,Promise构造函数接收一个函数作为参数,这个函数有两个参数resolve,reject,这两个参数也是方法,成功调用resolve(),失败调用reject(),实例创建完成后,可以使用then方法指定成功或者失败的回调函数,也可以用catch捕获失败,then和catch最后也是返回promise对象,所以可以链式调用。
以下是一个使用Promise的简单示例:
const promise = new Promise((resolve, reject) => {
// 模拟异步操作
setTimeout(() => {
const randomNumber = Math.random();
if (randomNumber > 0.5) {
resolve(randomNumber);
} else {
reject(new Error('Random number is less than 0.5'));
}
}, 1000);
});
promise.then((data) => {
console.log(data);
}).catch((error) => {
console.error(error);
});
在上面的示例中,我们创建了一个Promise对象,模拟了一个异步操作。如果生成的随机数大于0.5,Promise对象的状态会变为resolved,然后调用promise.then中的回调函数;如果生成的随机数小于等于0.5,Promise对象的状态会变为rejected,然后调用promise.catch中的回调函数。
Promise.resolve()方法用于将现有对象转为Promise对象。它有四种参数情况:
1. 参数是一个Promise实例:
//参数是一个Promise实例,resolve()将不做任何修改,直接返回这个实例。
let p = new Promise((resolve, reject) => {
resolve('foo');
});
let p1 = Promise.resolve(p);
p1.then(function(value) {
console.log(value); // 输出:foo
});
2. 参数是一个thenable对象(具有then方法的对象):
let thenable = {
then: function(resolve, reject) {
resolve(42);
}
};
let p2 = Promise.resolve(thenable);
p2.then(function(value) {
console.log(value); // 输出:42
});
3. 参数是一个原始值或普通对象:
let p3 = Promise.resolve('bar');
p3.then(function(value) {
console.log(value); // 输出:bar
});
let p4 = Promise.resolve({ name: 'Alice' });
p4.then(function(value) {
console.log(value); // 输出:{ name: 'Alice' }
});
4. 参数没有任何值:
let p5 = Promise.resolve();
p5.then(function() {
console.log('resolved');
});
Promise.reject()方法返回一个带有拒绝原因的Promise对象。它可以用于在Promise链中显式地拒绝一个Promise,并将拒绝原因传递给后续的catch()方法进行处理。
Promise.reject(new Error("BOOM!")).catch(error => { console.error(error); })
// 输出:Error: BOOM!
上述例子创建了一个被拒绝的Promise对象,并传递了一个Error对象作为拒绝原因。然后使用catch()方法来捕获并处理拒绝的Promise,
Promise.then()方法接受两个参数,分别是onFulfilled和onRejected。这两个参数都是函数,用于处理Promise对象的状态变为fulfilled(已完成)或rejected(已拒绝)时的回调函数。
onFulfilled是当Promise对象的状态变为fulfilled时调用的函数。它接收Promise对象的解决值作为参数,并返回一个新的Promise对象或一个值。如果返回一个新的Promise对象,则后续的then()方法将等待该Promise对象的状态变为fulfilled或rejected,并将其解决值传递给下一个then()方法。如果返回一个值,则后续的then()方法将立即被调用,并将该值作为解决值传递给下一个then()方法。
onRejected是当Promise对象的状态变为rejected时调用的函数。它接收Promise对象的拒绝原作为参数,并返回一个新的Promise对象或一个值。如果返回一个新的Promise对象,则后续的then()方法将等待该Promise对象的状态变为fulfilled或rejected,并将其解决值或拒绝原因传递给下一个then()方法。如果返回一个值,则后续的then()方法将立即被调用,并将该值作为解决值传递给下一个then()方法。
promise.then((value) => {
// 处理解决值
}, (reason) => {
// 处理拒绝原因
}).catch((error) => {
// 处理错误
});
与catch()方法相比,第二个参数onRejected和catch()方法的区别在于,onRejected只会处理当前Promise对象的拒绝原因,而catch()方法可以处理当前Promise对象及其后续Promise对象的拒绝原因。此外,catch()方法还可以在链式调用中更方便地捕获错误。
Promise.then(null,onOejected)用于指定当Promise对象的状态变为rejected时的回调函数。第一个参数为null,表示不处理Promise对象状态变为fulfilled的情况,第二个参数为一个回调函数,用于处理Promise对象状态变为rejected的情况。
let promise = new Promise((resolve, reject) => {
// 模拟异步操作
setTimeout(() => {
reject('Error occurred');
}, 2000);
});
promise.then(null, (error) => {
console.log(error); // 输出:Error occurred
});
// .catch()是.then(null, 参数)的别名,结果都是一样的
promise .catch(reason => {
console.log(reason); // 输出:Error occurred
});
/*这个例子表示promise对象的状态在2秒后变为rejected,并且传递了一个错误信息。
then方法的第一个参数为null,表示不处理状态变为fulfilled的情况,
第二个参数为一个回调函数,用于处理状态变为rejected的情况。*/
同理当promise.then()只有一个参数时,用于处理promise对象的成功状态。
两个方法的区别:
promise.all(iterable):iterable是由多个promise实例组成的可迭代对象(如Array, Map, Set),即将多个 Promise 对象包装成一个新的 Promise 实例。
当iterable中的promise实例都完成,所有实例都变为 fulfilled 状态时,该新的 Promise 实例才会变为 fulfilled 状态,返回所有成功的结果组成的数组,当任意一个 Promise 对象变为 rejected 状态时,该新的 Promise 实例就会变为 rejected 状态。只要有一个回调执行失败,then是不会执行的,则在catch中回调第一个失败的结果。
下面是 Promise.all 方法的用法和示例:
const promise1 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('Promise 1 resolved');
}, 2000);
});
const promise2 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('Promise 2 resolved');
}, 3000);
});
const promise3 = new Promise((resolve, reject) => {
setTimeout(() => {
reject('Promise 3 rejected');
}, 4000);
});
Promise.all([promise1, promise2, promise3])
.then((values) => {
console.log(values); // 输出:['Promise 1 resolved', 'Promise 2 resolved']
})
.catch((error) => {
console.log(error); // 输出:'Promise 3 rejected'
});
在上面的示例中,我们创建了三个 Promise 对象,分别是 promise1、promise2 和 promise3。promise1 和 promise2 分别在 2 秒和 3 秒后变为 fulfilled 状态,而 promise3 在 4 秒后变为 rejected 状态。
然后,我们使用 Promise.all 方法将这三个 Promise 对象包装成一个新的 Promise 实例,并通过 then 方法和 catch 方法分别处理 fulfilled 状态和 rejected 状态。
在 then 方法中,我们可以获取到所有 Promise 对象的结果值,以数组的形式返回。在 catch 方法中,我们可以获取到第一个变为 rejected 状态的 Promise 对象的错误信息。
promise.race(iterable):Promise.race(iterable)方法也接收一个可迭代对象作为参数,返回一个新的Promise对象。只要iterable中的任意一个promise实例resolved或者rejected,返回的promise就会resolved或者rejected。
const promise1 = new Promise((resolve, reject) => {
setTimeout(resolve, 500, 'one');
});
const promise2 = new Promise((resolve, reject) => {
setTimeout(resolve, 100, 'two');
});
Promise.race([promise1, promise2]).then((value) => {
console.log(value);
});
// 输出:'two'
例子:后端接口进阶写法,使用promise 、asyn/await同时返回两个数据给前端。
// 获取产品类别和总价
exports.getCategoryAndNumber = (req, res) => {
// 获取产品类别数组
const CategoryArr = () => {
return new Promise(resolve => {
const sql = 'select set_value from setting where set_name = "产品设置"'
db.query(sql, (err, result) => {
let str = result[0].set_value
// eval() JSON格式字符串转化为 JSON对象
const arr = eval('(' + str + ')')
resolve(arr)
})
})
}
// 获取价格
const getNumber = product_category => {
return new Promise(resolve => {
const sql = 'select product_all_price from product where product_category= ?'
db.query(sql,product_category,(err,result)=>{
let total = 0
for(let i =0;i<result.length;i++){
total += result[i]['product_all_price']
}
resolve(total)
})
})
}
// 通过循环类别数组里面每一个类别获取对应的价格
async function getAll(){
const category= await CategoryArr()
const price = []
for(let i =0 ;i <category.length;i++){
price[i] = await getNumber(category[i])
}
res.send({
category:category,
price:price
})
}
getAll()
}
Promise.finally():用于指定Promise对象的回调函数,无论Promise对象的状态是成功还是失败,该回调函数都会执行。
Promise.allSettled():接收一个Promise对象的数组作为参数,当这个数组中的所有Promise对象都变为fulfilled或rejected状态时,allSettled()返回一个新的Promise对象。
Promise.any():接收一个Promise对象的数组作为参数,当这个数组中的任意一个Promise对象变为resolved状态时,any()返回一个新的Promise对象。