JavaScript ES6 Promise 常见用法

Promise简介
  • Promise的出现是方便开发人员优雅地书写处理JavaScript中的异步任务。由于它是ECMAScript 6(ES6)中新增的类所以对于浏览器版本有一定的要求,具体如下:
ChromeEdgeFirefoxSafariOpera
Chrome 58Edge 14Firefox 54Safari 10Opera 55
JavaScript中关于异步处理
  • Promise出现之前在JavaScript中通常使用回调函数去处理异步任务结束后的工作。它的作用就好比我们告诉异步任务等你结束后要去干什么。
setTimeout(function () {
    console.log('3秒后打印这条信息');  // 三秒后子线程执行
}, 3000);
console.log('我先打印');              // 主线程先执行
  • 其中setTimeout的第一个参数就是一个回调函数,第二参数为等待时间。目前来看使用回调函数处理异步任务结束之后的工作并没有什么不妥,那为什么还要提出Promise呢?
  • 回调函数缺点:上边的示例中的异步任务都是一次异步,如果出现多次异步又该如何处理呢,可能就需要使用下边传统多次回调方式,这种方式虽然实现了多次异步处理但是最后生成的代码难以维护并且对于异常的处理非常不友好,这种方式也就是常说的回调陷阱。当然也可以使用Promise进行改造以达到同样效果。
// 传统多次回调
setTimeout(function () {
    console.log("First");
    setTimeout(function () {
        console.log("Second");
        setTimeout(function () {
            console.log("Third");
        }, 3000);
    }, 2000);
}, 1000);
// 使用Promise达到同样效果
new Promise(function (res, rej) {
    setTimeout(function () {
        console.log("First");
        res();
    }, 1000);
}).then(function () {
    return new Promise(function (res, rej) {
        setTimeout(function () {
            console.log("Second");
            res();
        }, 2000);
    });
}).then(function () {
    setTimeout(function () {
        console.log("Third");
    }, 3000);
});
Promise登场
  • 构造函数:Promise的构造函数接收一个函数作为参数,这个函数是同步的并且会被立即执行,也称之为起始函数。起始函数包含两个参数res(resolve)rej(reject),分别表示Promise成功失败状态。起始函数执行成功时,它应该调用 res 函数并传递成功的结果。当起始函数执行失败时,它应该调用 rej 函数并传递失败的原因。

  • Promise 构造函数返回一个 Promise 对象,该对象具有以下几个方法:

    • then:用于处理 Promise 成功状态的回调函数。
    • catch:用于处理 Promise 失败状态的回调函数。
    • finally:无论 Promise 是成功还是失败,都会执行的回调函数。
  • 一个小栗子

// 创建一个Promise对象
const promise = new Promise((res, rej) => {
  // 异步操作
  setTimeout(() => {
    if (Math.random() < 0.5) {
      res('小于0.5');
    } else {
      rej('大于等于0.5');
    }
  }, 1000);
});
// 调用Promise对象的then和catch方法
promise.then(res => {
  console.log(res); // 当生成随机数小于0.5时,打印构造函数中res传递出的'小于0.5'
}).catch(err => {
  console.log(err); // 当生成随机数大于等于0.5时,打印构造函数中rej传递出的'大于等于0.5'
}).finally(() => {
  console.log('总是会执行'); // 总是会打印此条信息
});
  • 异步函数(async、await)几乎被所有浏览器支持。
    使用async修饰的函数会返回一个Promise对象,可以使用then方法进行一些处理。而await命令后边通常会跟一个Promise对象,返回该对象的结果,如果不是Promise则直接返回对应的值。
  • 再来一个小栗子
// print是一个被async修饰的函数它返回的是一个Promise对象,正常return的值会被当做res函数的参数传递
async function print(num) {
	if (num == 0) {
		// 模拟函数内部报错,错误信息可以被catch捕获
		throw new Error("Divide zero");
	}
	// 模拟耗时操作
	let set = new Set();
	for (let i=0; i<10000000; i++) {
		set.add(i);
	}
	const result = 100 / num;
	return result;
}
// await后跟一个Promise对象,并且等待Promise对象执行完毕才会继续向下执行。参数修改为0则会被捕获异常也会继续往下执行
await print(10)
	// 正常结果
	.then(res => {
		console.log(res)
	})
	// 异常处理
	.catch(err => {
		console.log(err);
	});
// 这条打印会被阻塞,只有等待之前的print函数执行完毕才会执行打印
console.log('Over! Over!');
  • 多个Promise全部执行完毕后再进行一些操作可以借助Promise.all(params)all函数接收一个Promise对象数组,然后会将数组中全部的Promise对象执行完毕后再进行相关处理。下面又是一个小栗子:
const p1 = new Promise(function(res, rej) {
	setTimeout(function() {
		console.log('First');
		res('FirstResInfo');
	}, 1000);
});

const p2 = new Promise(function(res, rej) {
	setTimeout(function() {
		console.log('Second');
		res('SecondResInfo');
	}, 2000);
});

const p3 = new Promise(function(res, rej) {
	setTimeout(function() {
		console.log('Third');
		res('ThirdResInfo');
	}, 3000);
});

const promises = [p1, p2, p3];

Promise.all(promises)
	/*
	* 当p1、p2、p3全部执行完毕后会执行打印,此时的res不再是一个单独的字符串,
	* 而是一个字符串数组:['FirstResInfo', 'SecondResInfo', 'ThirdResInfo']
	*/
	.then(res => console.log(res))
	.catch(err => console.log(err));
  • 以上内容只是本人自己的一些关于Promise最基本用法的见解,肯定会存在不足之处。请大家友好讨论,不足之处希望大家多多包容。
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值