你的位置:首页 > 信息动态 > 新闻中心
信息动态
联系我们

Promise解决回调嵌套问题

2022/6/28 4:27:01

前言

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方法。