Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

模拟实现Promise #44

Open
conan1992 opened this issue Jul 2, 2020 · 0 comments
Open

模拟实现Promise #44

conan1992 opened this issue Jul 2, 2020 · 0 comments

Comments

@conan1992
Copy link
Owner

模拟实现

直接上代码

const PENDING = "pending";
const FULFILLED = "fulfilled";
const REJECTED = "rejected"
function MyPromise(executor){
	let self = this;
	self.status = PENDING;
	self.value = null;
	self.error = null;
	self.onFulfilled = [];
	self.onRejected = [];
	let resolve = (data) => {
		if(self.status !== PENDING) return;
		setTimeout(()=>{
			self.status = FULFILLED;
			self.value = data;
			self.onFulfilled.forEach(function(callback){
				callback((self.value))
			})
		})
	};
	let reject = (err) => {
		if(self.status !== PENDING) return;
		setTimeout(()=>{
			self.status = REJECTED;
			self.error = err;
			self.onRejected.forEach(function(callback){
				callback((self.error))
			})
		})
	}
	executor(resolve, reject)
}
MyPromise.prototype.then = function(onFulfilled, onRejected){
	let bridgePromise;
	let result;
	let self = this;
	onFulfilled = typeof onFulfilled === "function" ? onFulfilled : value => value;
	onRejected = typeof onRejected === "function" ? onRejected : error => {throw error};
	if(this.status===PENDING){
		//this.onFulfilled.push(onFulfilled);
		//this.onRejected.push(onRejected);
		return bridgePromise = new MyPromise((resolve, reject) => {
			self.onFulfilled.push((data)=>{
				try{
					let x = onFulfilled(data);
					resolvePromise(x, resolve, reject)
				}catch(e){
					reject(e)
				}
			});
			self.onRejected.push((error)=>{
				try{
					let x = onRejected(error);
					resolve(x)
				}catch(e){
					reject(e)
				}
			})
		})
	}else if(this.status === FULFILLED){
		return bridgePromise = new MyPromise((resolve, reject) => {
			setTimeout(function(){
				try{
					let x = onFulfilled(self.value);
					resolvePromise(x, resolve, reject)
				}catch(e){
					reject(e)
				}
			})
		})
	}else if(this.status === REJECTED){
		return bridgePromise = new MyPromise((resolve, reject) => {
			setTimeout(function(){
				try{
					let x = onRejected(self.error);
					resolvePromise(x, resolve, reject)
				}catch(e){
					reject(e)
				}
			})
		})
	}
	return result || this;
}
MyPromise.prototype.catch = (onRejected)=>{
	return this.then(null, onRejected)
}
function resolvePromise( x, resolve, reject){
	if(x instanceof MyPromise){
		if(x.status === PENDING){
			x.then(y=>{
				resolvePromise(y, resolve, reject)
			}, error=>{
				reject(error)
			})
		}else{
			x.then(resolve, then)
		}
	}else{
		resolve(x)
	}
}

测试代码

var readImg = function(url){
	return new MyPromise(function(resolve, reject){
		var img = new Image();
		img.src = url;
		img.onload = function(){
			reject(img);
		};
	})
}
var foo = readImg("./0.jpg")
var b = foo.then(data => {
	console.log("第一次展示: ", data);
	return readImg("./1.jpeg")
}, error=>{
	return "123"
}).then(data => {
	console.log(data)
});

关键点

  • 第一个Promise resolve之后返回值的问题;再利用一个Promise,在第一个Promise执行resolve回调之后,把返回值通过第二个resolve传递...如果返回值也是Promise利用resolvePromise将数据利用递归转成非Promise
  • catch其实就是then的语法糖
MyPromise.prototype.catch = (onRejected)=>{
	return this.then(null, onRejected)
}

参考

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant