Promise(2)-解决回调地狱

362 阅读1分钟

我们刚开始说了,promise是为了解决回调嵌套而生的,最常用的就是把异步方法变为promise,下面我们就来尝试一下。

先看看最基本的用法:

function read(...args) {
	return new Promise((resolve, reject) => { 
     	fs.readFile(...args, function(err, data) {
     		if (err) reject(err);
     		resolve(data);
     	});
	});
}
read('./name.txt', 'utf8').then(data => {
	return read(data, 'utf8');
}).catch(err => {
	console.log('catch错误', err);
});

上面我们用new Promise()做了一层包装,这其实也是多了一层嵌套,还是可以改进的,我们给Promise定义一个新的方法

Promise.defer = Promise.deferred = function() {
	let dfd = {};
	dfd.promise = new Promise((resolve, reject) => {
		dfd.resolve = resolve;
		dfd.reject = reject;
	});
	return dfd;
}

它最终返回了一个对象,也叫延迟对象,主要做法是把promise内部的resolve和reject放在了外部,这样就不需要再像上面那样放在new Promise()内部去使用了。应用到上面的例子

function read(...args) {
	let dfd = Promise.defer();
	fs.readFile(...args, function(err, data) {
		if (err) dfd.reject(err);  
		dfd.resolve(data);
	});
	return dfd.promise;
}

这样是不是看上去好多了呢?

上面的处理只是在使用某个具体的方法可以很方便的把一个异步方法改为promise, 但是如果我们想有一个方法,能够把所有异步方法都改为promise呢?其实node给我们提供了一个方法promisify

let { promisify} = require('util');
let readFile = promisify(fs.readFile);

我们可以自己实现一个

function promisify(fn) {
	return function(...args) {
		return new Promise((resolve, reject) => {
			fn(...args, function(err, data) {
				if (err) reject(err);
				resolve(data);
			});
		});
	}
}

let readFile = promisify(fs.readFile);

promisify返回一个函数,这个函数最终返回一个promise。