前言
node.js最大的特色就是利用回调函数的方式来异步执行,但是回调函数的出现引发了回调过度嵌套的问题(回调金字塔),例如a嵌套b,b再嵌套c,c再嵌套D。例如,我们模拟一个页面元素移动的功能,点A移动到B后,B再移动到C,C再移动到D,D再移动到E,使用函数嵌套的方式如下:
function movea() { console.log('我是A,我已经移动到B的位置了哦'); moveb(function(value) { movec(function(value) { moved(); }) }) } function moveb(callback) { console.log('我是B,我已经移动到C的位置了哦'); callback(); } function movec(callback) { console.log('我是C,我已经移动到D的位置了哦'); callback(); } function moved() { console.log('我是D,我已经移动完毕'); } movea();可以看到,movea函数里面有一层一层的嵌套,有没有什么办法可以解决此问题呢?答案是Promise。
什么是Promise
书上这么说:
Promise 是异步编程的一种解决方案,比传统的解决方案–回调函数和事件--更合理和更强大。它由社区最早提出和实现,ES6将其写进了语言标准,统一了语法,原生提供了Promise我的理解:
Promise规范可以用链式调用的方式来解决函数过度嵌套的问题。 例如,上面的函数可以使用movea().moveb().movec()的方式来实现。Promise的原理
Promise的三种状态 pending:进行中 fulfilled :执行成功 rejected :执行失败 注意Promise在某一时刻只能处于一种状态
Promise的状态改变 pending------》fulfilled(resolved) pending------》rejected Promise的状态改变,状态只能由pending转换为rejected或者rejected,一旦状态改变完成后将无法改变(不可逆性)
使用Promise来改造嵌套函数
// Promise/A+规范 function moveaPromise() { return new Promise((resolve, reject) => { console.log('我是A,我已经移动到B的位置了哦'); resolve(); /*if (...) { reject(value); } else { resolve(value); }*/ }); } console.log('begin'); moveaPromise() .then(() => { console.log('我是B,我已经移动到C的位置了哦'); return true; }) .then(() => { console.log('我是C,我已经移动到D的位置了哦'); return true; }) .then(() => { console.log('我是D,我已经移动到D的位置了哦'); }) .catch((err) => { console.log('报了一个错误:' + err); }) console.log('end');如上,利用promise,就可以像链式调用的方式来调用回调函数了。
如果在moveaPromise函数中触发了resolve函数,则会执行后续的then方法,如果触发了reject函数,则会跳过后续的then方法,执行后续的catch方法。如果在then方法中跑出了异常,则会跳过后续的then方法,执行catch方法。