Promise用法及模拟实现

new Promise(function(resolve, reject){ … } /* executor */)

Promise是一个构造函数,执行时立即调用executor函数,resolve和reject两个函数作为参数传递给executor。
resolve, reject函数被调用分别会将promise状态改为fulfilled(完成)或rejected(失败)

var promise1 = new Promise(function(resolve, reject) {
  setTimeout(function() {
    resolve('foo');
  }, 300);
});

这个构造函数必须接受一个函数,否则会报错:
在这里插入图片描述

Promise.resolve(value)
类方法,返回一个以给定value决定的Promise对象。
1.如果该值是thenable(即带有then方法),返回的Promise对象的最终状态由then方法执行决定;
2.如果该value为空、基本类型或者不带then方法的对象,则返回的Promise对象状态为fulfilled,并且将该value传递给对应的then方法;

let p0 = new Promise(function(resolve, reject){
	setTimeout(function(){
		resolve('success');
	}, 250);
});
let p1 = Promise.resolve(p0);
console.log(p0 === p1); // true
p1.then(function(msg){
	console.log('Yay! ' + msg); // Yay! success
})

传入 thenable 对象,返回 Promise 对象跟随 thenable 对象的最终状态。

Promise.reject(reason)
Promise.reject(reason)方法也会返回一个新的Promise实例,该实例的状态为rejected。参数reason会被传递给实例的回调函数。

let p0 = Promise.reject('error');
p0.then(null, function(err){
	console.log(err);
});
// error

在这里插入图片描述
Promise.prototype.then
最多可接受两个参数,Promise的成功和失败情况的回调

let p0 = new Promise(function(resolve, reject){
	//异步操作
	setTimeout(function(){
		// 生成1-10之间的随机数
		var num = Math.ceil(Math.random() * 10);
		if(num <= 5){
			resolve(num);
		}else {
			reject('err');
		}
	}, 1000);
});
p.then(function(res){
	console.log('resolved', res);
}, function(err){
	console.log('rejected', err);
})

会随机的执行resolve,reject的方法;
then方法接受的参数是函数,但如果传递的并非是一个函数,那么then将创建一个没有经过回调函数处理的新的Promise对象,这个新Promise只是简单的接受调用这个then的原Promise的终态作为它的终态。

Promise.resolve(1)
  .then(2)
  .then(Promise.resolve(3))
  .then(console.log)
  // 1

Promise.prototype.catch
该方法和then的第二个参数一样,用来指定reject的回调:

p.then(function(res){
	console.log('resolved', res);
}).catch(function(err){
	console.log('rejected', err);
});

但它们之前还有个区别,就是在执行then中第一个参数即resolve的回调时,如果代码执行报错或异常,那么就会进到这个catch方法中:

p.then(function(res){
	console.log('resolved', res);
	console.log(error); // 未定义
}).catch(function(err){
	console.log('rejected', err);
});

在这里插入图片描述
Promise.all(itertable)
在 iterable 参数内所有的 promise 都“完成(resolved)”或参数中不包含 promise 时回调完成(resolve);如果参数中 promise 有一个失败(rejected),此实例回调失败(reject),失败原因的是第一个失败 promise 的结果。

var promise1 = Promise.resolve(3);
var promise2 = 42;
var promise3 = new Promise(function(resolve, reject) {
  setTimeout(resolve, 100, 'foo');
});

Promise.all([promise1, promise2, promise3]).then(function(values) {
  console.log(values);
});
// [3, 42, "foo"]

Promise.race(itertable)
返回一个 promise,一旦迭代器中的某个promise解决或拒绝,返回的 promise就会解决或拒绝。

var promise1 = new Promise(function(resolve, reject) {
    setTimeout(resolve, 500, 'one');
});

var promise2 = new Promise(function(resolve, reject) {
    setTimeout(resolve, 100, 'two');
});

Promise.race([promise1, promise2]).then(function(value) {
  console.log(value);
  // 谁先执行完,就以谁为准执行回调
});
// "two"

下面实现一个简单的Promise:
大体结构如下:

function Promise(resolver){
	if(typeof resolver !== 'function'){
		throw new Error('Promise resolver undefined is not a function');
	}
	// 当前promise对象的状态
	var status = 'pending',
	// 当前promise对象的数据
		value = undefined,
	// 当前对象注册的回调方法队列
		callbacks = [];
	function resolve(newValue) {}
	function reject(err) {}
	resolver(resolve, reject);
	this.then = function(onFulfilled, onRejected) {}
}
Promise.all = function(iterable) {}
Promise.race = function(iterable) {}

下面来实现resolve方法:

function resolve(newValue) {
	if(newValue && (typeof newValue === 'object' || typeof newValue === 'function')){
		var then = newValue.then;
		if(typeof then === 'function'){
			then.call(newValue, resolve, reject);
			return;
		}
	}
	status = 'fulfilled';
	value = newValue;
	executeCallbacks(); //执行回调
}

reject方法

function reject(err) {
	status = 'rejected';
	value = err;
	executeCallbacks();
}

处理executeCallbacks方法:

function executeCallbacks() {
	setTimeout(function(){
		callbacks.forEach(function(cb){
			handle(cb);
		});
	}, 0);
}

then方法:

this.then = function(onFulfilled, onRejected) {
	// 链式调用,会返回一个新的Promise
	return new Promise({
		handle({
			onFulfilled: onFulfilled || null,
			onRejected: onRejected || null,
			resolve,
			reject
		});
	});
}

处理handle函数:

function handle(callback) {
	if(status == 'pending'){
		callbacks.push(cb);
		return;
	}
	var cb = status == 'resolved' ? callback.onFulfilled : callback.onRejected;
	if(cb === null){
		cb = status == 'resolved' ? callback.resolve : callback.reject;
		cb(value);
		return;
	}
	var ret = cb(value);
	try{
		callback.resolve(ret);
	}catch(err){
		callback.reject(err);
	}
}

最后咱们实现Promise.all

Promise.all = function(iterable) {
	var self = this;
	return new this(function(resolve, rejct){
		if(!iterable || !Array.isArray(iterable)){
			return reject(new TypeError('must be an array'));
		}
		var len = iterable.length;
		if(!len){return resolve([])};
		var results = [], called = false;
		iterable.forEach(function(it, index){
			(function(i){
				self.resolve(it).then(function(res){
					results[i] = res;
					if(!called && results.length == len){
						called = true;
						return resolve(results);
					}
				}, function(err){
					called = true;
					return reject(err);
				});
			})(index);
		});
	});
}

实现Promise.race

Promise.race = function(iterable){
	var self = this;
	return new this(function(resolve, rejct){
		if(!iterable || !Array.isArray(iterable)){
			return reject(new TypeError('must be an array'));
		}
		var len = iterable.length;
		if(!len){return resolve([])}
		var called = false;
		iterable.forEach(function(it){
			self.then(functoin(res){
				if(!called){
					called = true;
					return resolve(res);
				}
			}, function(err){
				if(!called){
					called = true;
					return reject(err);
				}
			});
		});
	});
}

参考资料: 深入理解Promise
MDN Promise
30分钟,让你彻底明白Promise原理

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值