Promise用法和理解(Node篇)

解决问题:回调地狱(callback hell)
引用很经典的一张图,可以看出回调地狱带来的不友好的书写方式
Promise用法和理解(Node篇)_第1张图片
例:使用Node按顺序异步读取文件(与浏览器中运行使用异步方法同理)

const fs = require('fs');

fs.readFile('./static/a.txt','utf8',function(err,data){
	if(err){
        //抛出异常
        //作用:阻止程序执行,并把错误信息打印到控制台
		throw err;
	}
	console.log(data);
});
fs.readFile('./static/b.txt','utf8',function(err,data){
	if(err){
		throw err;
	}
	console.log(data);
});
fs.readFile('./static/c.txt','utf8',function(err,data){
	if(err){
		throw err;
	}
	console.log(data);
});

上述代码中,可以看出同时执行了三个异步方法,按照原本的需求,需要按顺序读取三个文件a.txt->b.txt->c.txt,虽然代码中我们是按照先后的顺序书写的,但是执行的顺序不一定是按照书写的顺序,由于是异步方法,不需要等待,打印的顺序取决于读取的文件大小

控制台打印结果
可以看出,多次打印,确实会出现打印顺序不一致的情况

E:\笔记\js>node promise.js
hello a
hello b
hello c

E:\笔记\js>node promise.js
hello a
hello c
hello b

E:\笔记\js>node promise.js
hello a
hello b
hello c

为了保证文件的读取顺序,可以使用回调嵌套的方式

fs.readFile('./static/a.txt', 'utf8', function (err, data) {
  if (err) {
    throw err;
  }
  console.log(data);
  fs.readFile('./static/b.txt', 'utf8', function (err, data) {
    if (err) {
      throw err;
    }
    console.log(data);
    fs.readFile('./static/c.txt', 'utf8', function (err, data) {
      if (err) {
        throw err;
      }
      console.log(data);
    });
  });
});

上述的代码虽然解决了读取顺序的问题,但是同时也产生了文章开头所说的回调地狱的问题,这就是我们为什么要使用Promise?

Promise介绍

Promise是ES6新增的API
Promise的英文就是承诺,保证的意思
三种状态:1. Pending(默认状态)2. Resolved(成功)3. Rejected(失败)
Promise相当于一个容器,本身不是异步,里面的任务是异步

Promise基础语法

//创建Promise容器(构造函数)
var p1 = new Promise(function(resolve,reject){
	fs.readFile('./static/a.txt','utf8',function(err,data){
		if(err){
			// 失败,容器中的任务失败
			// console.log(err);
			reject(err);//把容器的Panding状态变为Rejected,实际上就是then方法传递的方法2
		}
		//容器中的任务成功
		// console.log(data);
		resolve(data);//把容器的Pending改为Resolved,实际上就是then方法传递的方法1
	});
});

//当p1成功了就是then(英文意思:然后)
p1.then(function(data){
	console.log(data);
},function(err){
	console.log(err);
})

then方法链式调用读取文件

//创建Promise容器(构造函数)
var p1 = new Promise(function(resolve,reject){
	fs.readFile('./static/a.txt','utf8',function(err,data){
		if(err){
			// 失败,容器中的任务失败
			// console.log(err);
			reject(err);//把容器的Panding状态变为Rejected,实际上就是then方法传递的方法2
		}
		//容器中的任务成功
		// console.log(data);
		resolve(data);//把容器的Pending改为Resolved,实际上就是then方法传递的方法1
	});
});

var p2 = new Promise(function(resolve,reject){
	fs.readFile('./static/b.txt','utf8',function(err,data){
		if(err){
			// 失败,容器中的任务失败
			// console.log(err);
			reject(err);//把容器的Panding状态变为Rejected,实际上就是then方法传递的方法2
		}
		//容器中的任务成功
		// console.log(data);
		resolve(data);//把容器的Pending改为Resolved,实际上就是then方法传递的方法1
	});
});

var p3 = new Promise(function(resolve,reject){
	fs.readFile('./static/c.txt','utf8',function(err,data){
		if(err){
			// 失败,容器中的任务失败
			// console.log(err);
			reject(err);//把容器的Panding状态变为Rejected,实际上就是then方法传递的方法2
		}
		//容器中的任务成功
		// console.log(data);
		resolve(data);//把容器的Pending改为Resolved,实际上就是then方法传递的方法1
	});
});

//当p1成功了就是then(英文意思:然后)
p1.then(function(data){
		//p1读取成功时候
		console.log(data);
		// 当前函数中return的结果就可以在后面的then的function中接收
		return p2;//返回p2这个Promise对象
	},function(err){
		console.log(err);
	})
	.then(function(data){
		console.log(data);//打印p2 resolve返回的值
		return p3;//返回p3这个Promise对象
	})
	.then(function(data){
		console.log(data);//打印p3 resolve返回的值
	});

上述代码虽然长,但是代码结构清晰(then中参数二可不传

简化代码,我们可以使用Promise封装读取文件的方法

// 封装读取文件的方法
function PromiseReadFile(filePath){
	// 返回一个Promise对象
	return new Promise(function(resolve,reject){
		fs.readFile(filePath,'utf8',function(err,data){
			if(err){
				// 失败,容器中的任务失败
				// console.log(err);
				reject(err);//把容器的Panding状态变为Rejected,实际上就是then方法传递的方法2
			}
			//容器中的任务成功
			// console.log(data);
			resolve(data);//把容器的Pending改为Resolved,实际上就是then方法传递的方法1
		});
	});	
}

// 链式调用
PromiseReadFile('./static/a.txt')
	.then(function(data){
		console.log(data);
		return PromiseReadFile('./static/b.txt');
	})
	.then(function(data){
		console.log(data);
		return PromiseReadFile('./static/c.txt');
	})
	.then(function(data){
		console.log(data);
	});

以上就是Promie的基本使用,通过封装可以看出代码结构更加简洁明了,从而避免了回调地狱带来的问题,使代码看上去更加优雅

你可能感兴趣的:(日志,javascript)