从回调地狱到Promise

111 阅读2分钟

一、啥是回调地狱 先看一段代码:

// 第一版
setTimeout(()=>{
	console.log(111);
	setTimeout(()=>{
		console.log(222);
		setTimeout(()=> {
			console.log(333);
		},1000)
	},2000);
},3000)

像这样的代码就是回调地狱,这段代码意思很明确,就不过多说明了 这段代码可以适当封装一下:

// 第二版
const createTimer = (callback, delay) => {
	let timer = null;
	return () => {
		clearTimer(timer);
		timer = setTimeout(callback, delay);
	};
};

const timer1 = createTimer(()=>{
	console.log(111);
	const timer2 = createTimer(()=>{
		console.log(222);
		const timer3 = createTimer(()=>{
			console.log(333);
		},1000);
		timer3();
	},2000);
	timer2();
},3000)
timer1();

看到了没,回调地狱式的写法,不管怎么封装,它始终都是嵌套在一起的,可读性极差,这还是比较简单的情况。层级越复杂会嵌套得越深,可读性越差。

二、如何解决回调地狱 如何解决,使用Promise:

// 第三版
const createTimer = (callback, delay) => {
	let timer = null;
	return () => {
		clearTimer(timer);
		timer = setTimeout(callback, delay);
	};
};
// 封装promise
const getPromise = (data, time) => {
	return new Promise((resolve, reject)=>{
		const timer1 = createTimer(() => {
			resolve(data);
		}, time);
		timer1();
	});
}

// 调用promise
const promise1 = getPromise(111,3000);
promise1.then(res=>{
	console.log(res);
	const promise2 = getPromise(222,2000);
	return promise2;
}).then(res=>{
	console.log(res);
	const promise3 = getPomise(333,1000);
	return promise3;
}).then(res=>{
	console.log(res);
})

promise 的用法是将传递的数据通过resolve或reject保存到promise对象中,通过then方法获取数据。 用了promise后,可以直观的发现代码可读性有一定的提高,它解决了异步函数的执行顺序问题。 但链式调用可读性还是很差,并且也不容易调试。 再介绍一下async/await

三、async/await

// 第四版
const createTimer = (callback, delay) => {
	let timer = null;
	return () => {
		clearTimer(timer);
		timer = setTimeout(callback, delay);
	};
};
// 封装promise
const getPromise = (data, time) => {
	return new Promise((resolve, reject)=>{
		const timer1 = createTimer(() => {
			resolve(data);
		}, time);
		timer1();
	});
}
// 使用 async/await
const AsyncFunction = async () => {
	const res1 = await getPromise(111,3000);
	console.log(res1);
	const res2 = await getPromise(222,2000);
	console.log(res2);
	const res3 = await getPromise(333,1000);
	console.log(res3);
}
AsyncFunction();

这里我们可以发现 async/await 摆脱了链式调用, 更像是同步代码,看起来更加的优雅简洁。 大家可以把这三种写法详细对比一下,体会一下差异在哪。