彻底弄懂Promise!!!

发布时间:2024年01月12日

目录

一、什么是Promise

二、为什么使用Promise

三、Promise的基本用法

四、Promise.resolve()与Promise.reject()

五、Promise.then与Promise.catch

六、Promise.all(iterable)与Promise.race(iterable)

七、使用场景

补充


一、什么是Promise

Promise是一种用于处理异步操作的JavaScript对象。它代表了一个尚未完成但最终会完成的操作,并可以返回操作的结果或错误信息。Promise对象有三种状态:pending(进行中)、fulfilled(已完成)和rejected(已拒绝)。当操作完成时,Promise对象可以从pending状态转变为fulfilled状态,表示操作成功完成;或者从pending状态转变为rejected状态,表示操作失败。

二、为什么使用Promise

使用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的基本用法

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.reject()

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与Promise.catch

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)与Promise.race(iterable)

两个方法的区别:

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()
}

补充

  1. Promise.finally():用于指定Promise对象的回调函数,无论Promise对象的状态是成功还是失败,该回调函数都会执行。

  2. Promise.allSettled():接收一个Promise对象的数组作为参数,当这个数组中的所有Promise对象都变为fulfilled或rejected状态时,allSettled()返回一个新的Promise对象。

  3. Promise.any():接收一个Promise对象的数组作为参数,当这个数组中的任意一个Promise对象变为resolved状态时,any()返回一个新的Promise对象。

文章来源:https://blog.csdn.net/weixin_52645312/article/details/135557665
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。