一,回调函数
1,什么是回调函数
回调函数就是将一个方法作为一个参数,传入另一个函数,当这个函数执行时,满足某个条件时执行当做参数的这个方法。
2,回调函数的形式
// fs模块 读取两个文件内容 将结果拼接输出
var fs=require("fs");
var database;
fs.readFile("./f1.txt",function(err,data){
fs.readFile("./f2.txt",function(err,data2){
databaase=data.toString()+data2.toString();
console.log(database)
});
})
3,回调函数的问题
3,1 由于回调函数是嵌套的,如果有很多回调函数的时候,代码就会很多的缩进,看起来很不和谐。
// fs模块 读取两个文件内容 将结果拼接输出
var fs=require("fs");
var database;
fs.readFile("./f1.txt",function(err,data){
fs.readFile("./f2.txt",function(err,data2){
fs.readFile("./f3.txt",function(err,data3){
fs.readFile("./f4.txt",function(err,data4){
fs.readFile("./f5.txt",function(err,data5){
fs.readFile("./f6.txt",function(err,data6){
fs.readFile("./f7.txt",function(err,data7){
databaase=data.toString()+data2.toString()+data3.toString()+data4.toString()+data5.toString()+data6.toString()+data7.toString();
console.log(database)
});
});
});
});
});
});
})
3,2当有一段代码需要在多个异步任务都完成时,才执行,使用回调函数的话,会非常的麻烦。
- 回调函数需要多层嵌套
- 多个异步任务的执行是串行的,而不是并发的
二,promise对象
1,什么是promise对象
promise对象是ES6新增的,为了解决回调函数的多层嵌套问题,用于封装异步任务
2:语法
使用构造函数创建Promise对象,参数是一个函数,函数中写异步任务的代码。
参数函数中有两个参数,resolve和reject,这两个参数也是函数。
let p1=new Promise(function(resole,reject){
fs.readFile("./f1.txt",function(err,data){
if(!err){
//异步任务执行成功时,调用resolve().如果有数据会传给.then回调函数。
resolve(data);
}else{
//异步任务执行失败时,调用reject().err会传给.catch回调函数。
reject(err);
}
}
}
p1.then(function (d) {
// 文件读取成功
console.log(d.toString());
});
// promise对象的.catch方法,为promise对象添加任务失败时的回调函数,回调函数会在promise变为失败状态时执行,如果promise已经是失败状态则会立刻执行。
p1.catch(function (err) {
// 文件读取失败
console.log(err);
});
3:两个参数,两种状态,两个回调函数
两个参数:
resolve
reject
两种状态:
resolve(); //resolve(data); 任务成功时状态
reject(); //reject(err); 任务失败时状态
两个回调函数:
then();任务成功时,会执行此回调函数。
catch();任务失败时会执行此回调函数。
PS:
1,
promise对象,创建之后就会立刻调用异步任务所在函数。
2,
promise对象有一个状态属性,刚创建成功的promise,处于待定状态(padding),如果promise中函数调用了resolve(异步任务成功),则由待定状态转为完成状态(sucess)。如果promise中的函数调用了reject(异步任务失败),则会由待定状态转为失败(fail)。一个promise对象的状态一但由待定转为成功或失败,则它的状态就确定了。
3,
promise对象的.then方法,用于为promise对象添加任务成功时的回调函数。回调函数会在promise对象变为完成状态时执行,如果promise已经处于完成状态,则会立刻执行。
4,
promise对象的.catch方法,为promise对象添加任务失败时的回调函数,回调函数会在promise变为失败状态时执行,如果promise已经是失败状态则会立刻执行。
三,promise封装成方法
对于promise对象,一般不会直接封装一个异步任务,而是将封装promise的过程写成一个方法,专门用于封装某种类型的异步任务,例如,对于文件读取,可以写一个自己的myReadFile,返回一个promise。
// myReadfile函数
function myReadfile(path) {
// 将封装的promise返回
return new Promise(function (resolve, reject) {
// 文件读取
fs.readFile(path, function (err, data) {
if (!err) {
// 读取成功
resolve(data.toString());
}
else {
// 读取失败
reject(err);
}
});
});
}
// 调用函数 链式调用,成功,失败时的状态
myReadfile("./f1.txt")
// 成功时,执行的回调函数
.then(function(data){
console.log(data)
})
// 失败时执行的回调函数
.catch(function(err){
console.log(err);
})
三,promise对象合并
使用promise读取多个文件内容时,多个异步任务必须先后执行。
var d1;
myReadfile("./f1.txt")
.then(function (data) {
d1 = data;
// 在一个promise对象的.then函数中,可以return另一个promise对象。.then方法的返回值就是这个新的promise对象,所以可以再次.then添加新promise的.then方法。
return myReadfile("./f2.txt")
})
.then(function (data) {
// console.log(d1+data);
})
// 多promise连续.then时,最后只需要一个.catch
.catch(err => {
console.log(err);
})
// 多异步任务并发执行
let p2 = myReadfile("./f1.txt");
let p3 = myReadfile("./f2.txt");
// Promise.all方法,将多个promise对象合并成一个peomise对象,当和并的每一个promise对象都变为完成状态时,总的promise对象才变为完成状态。只要有一个promise失败,总的promise对象就变为失败状态。
let total = Promise.all([p2, p3]);
total.then(function (data) {
// 数组的join方法 将数组拼接为一个字符串。
// 合并之后的promise对象的.then函数中,参数是一个数组,数组中记录了参与合并的每个promise对象.then的参数。
console.log(data.join(""));
})
.catch(function (err) {
console.log(err);
})```