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

被折叠的 条评论
为什么被折叠?



