promise解决回调地狱问题

一般来说,我们希望请求数据的代码简洁清晰,具有可读性,所以对重复请求的数据一般可复用是最好的了,故可以封装成一个函数,那么此时会出现一个问题,数据请求是一个异步的过程,无法保证是多个数据请求时返回的顺序,那么如果我们按照同步的逻辑将他们嵌套在一起,此时就会出现一个回调地狱的问题,并且一眼看不出这些代码到底是干什么,必须得读到嵌套得最深处;

此时promise可以解决回调地狱得问题,使得代码串联在一起,用 .then属性有序得输出,如果需要查寻某个数据,只需要找到上一层即可;

promise就是控制异步请求流程的,(具体请看示例3,详细过程参考示例1、2)

? 什么是同步和异步,可以去看我的" 什么是同步和异步 "。

示例1:数据请求封装成一个函数的遗留的异步请求顺序问题

const fs = require("fs");
function getData(path, resData, errfn) {
    fs.readFile(path, "utf8", function(err, data) {
        if (err) {
            // 如果报错,则执行errfn函数,返回想要的文本拼接
            return errfn(err);
        }
        // console.log(data);
        resData(data);
    });
}
// getData("./files/1.txt");
/* 但是有一个问题,我想在返回的数据上拼接上一些信息,可是现在无法拼接,不灵活
 所以我们需要将里面的输出也封装成一个参数传入,这样到时候文件读取成功时,
 可以执行这个函数,返回我想要的内容
 getData("你好", "./files/2.txt"); //此时这样是无法传参的,
 */
// 为了请求复用,所以用一个函数getData()来封装,然后传参调用
getData("./files/1.txt", function(data) {
    console.log("你好", data);
}, function(err) {
    console.log(" 错误", err.message)
});
getData("./files/2.txt", function(data) {
    console.log("hello,这是", data);

}, function(err) {
    console.log("错误", err.message)
});
// 但是上面虽然可以实现我们想要的数据结果,可是出现了数据的异步返回,
// 并不能保证返回的数据顺序

执行结果:这个结果明显返回的顺序不一致

示例2:解决返回顺序不一致的问题

// 我们这时用同步的思想嵌套来实现有顺序的输出,可是我们顾虑的就多了
// 会出现代码污染以及报错后面代码无法执行的问题
getData("./files/1.txt", function(data) {
    console.log("请求成功,这是", data);
    getData("./files/2.txt", function(data) {
        console.log("请求成功,这是", data);
        getData("./files/3.txt", function(data) {
            console.log("请求成功,这是", data);
        });
    });
});

执行结果:请求的数据返回顺序是一致的

但是上面可以解决顺序问题,可是会出现回调地狱(代码污染以及报错后面代码无法执行的问题)

所以用promise来解决回调地狱

示例3:创建可复用且解决回调地狱的函数封装,即用promise实例

//导入文件模块
const fs = require("fs");
// function getData(path, datafn, errfn) {
//     // new Promise()是立即执行构造函数的代码的,构造函数是隐含return的
//     return new Promise(function() {
//         fs.readFile(path, "utf8", function(err, data) {
//             if (err) {
//                 // return console.log(err)
//                 errfn(err.message);
//             }
//             // console.log(data)
//             datafn(data);
//         });
//     });
// }
// getData("./files/1.txt", function (data) {
//     console.log(data)
// }, function (err) {
//     console.log(err.message)
// });

// 相当于下面,只不过是将作为参数的函数用.then方法传到promise实例的函数的形参
function getData(path) {
    // new Promise()是立即执行构造函数的代码的,构造函数是隐含return的
    return new Promise(function(resolve, reject) {
        fs.readFile(path, "utf8", function(err, data) {
            if (err) {
                // return console.log(err)
                reject(err.message);
            }
            // console.log(data)
            resolve(data);
        });
    });
}
getData("./files/1.txt").then(function(data) {
    console.log(data)
        // 此时必须再返回一个promise构造函数的实例,也就是翻出去你需要请求的数据调用,这样才能继续用.then
        // .then 是promise对象的一个属性
    return getData("./files/2.txt");
    // 如果报错,可以继续执行后面的代码
}, function(err) {
    console.log(err.message)
    return getData("./files/2.txt");
}).then(function(data) {
    console.log(data);
    return getData("./files/3.txt");
}).then(function(data) {
    console.log("文本3", data)
});

执行结果:请求的数据执行顺序与代码一致

此时回调地狱的问题就解决了,当然在ajax请求、定时器这些情景中都可以用promise来解决!

Promise 是一种用于处理异步操作的对象,它可以有效地解决回调地狱问题回调地狱是指当多个异步操作依赖于前一个操作的结果时,嵌套的回调函数会导致代码难以理解和维护。 通过使用 Promise,我们可以将异步操作的结果链接在一起,形成一个链式调用。Promise 提供了两个特殊的方法:`then` 和 `catch`。 使用 `then` 方法,我们可以在前一个操作完成后执行下一个操作,并将结果传递给下一个操作。这样可以避免嵌套的回调函数。 使用 `catch` 方法,我们可以捕捉链式调用中出现的任何错误,并进行相应的处理。 下面是一个使用 Promise 解决回调地狱问题的示例代码: ```javascript function asyncOperation1() { return new Promise((resolve, reject) => { // 异步操作1 // 在操作完成后调用 resolve 或 reject }); } function asyncOperation2() { return new Promise((resolve, reject) => { // 异步操作2 // 在操作完成后调用 resolve 或 reject }); } function asyncOperation3() { return new Promise((resolve, reject) => { // 异步操作3 // 在操作完成后调用 resolve 或 reject }); } asyncOperation1() .then(result1 => { // 处理异步操作1的结果 return asyncOperation2(); }) .then(result2 => { // 处理异步操作2的结果 return asyncOperation3(); }) .then(result3 => { // 处理异步操作3的结果 }) .catch(error => { // 处理错误 }); ``` 在上述示例中,每个异步操作返回一个 Promise 对象,并在操作完成后调用 resolve 或 reject。通过使用 `then` 方法,我们将每个操作链接在一起,形成一个链式调用。如果任何操作失败,会自动跳转到 `catch` 方法进行错误处理。 使用 Promise 可以让异步代码更易于理解和维护,避免回调地狱问题的出现。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值