手写promise实现promiseA+规范,通过了官方的872个测试用例

6aadde73e46620d5bd6535eeb7df10e4.png

地址 ⬇️

github.com/webVueBlog/…

  1. promise是具有then行为符合本规范的方法或函数

  2. thenable是定义then方法的对象或函数

  3. value是任何合法的js值(undefined, thenable, promise)

  4. 异常是使用throw语句抛出的值

  5. reason是一个值,表示一个承诺被拒绝的原因

npm init -y

npm i promises-aplus-tests -D

adapter适配器

var promisesAplusTests = require('promises-aplus-tests');
promisesAplusTests(adapter, function(err) {});

promisesAplusTests(adapter, {reporter: 'dot'}, function(err) {
	
})
复制代码
./node_modules/.bin/promises-aplus-tests src/promise.js
复制代码

index.js

const Promise = require('./promise')
// new Promise传函数, then方法
// 第一个成功 100
// 第二个promise成功 100
let p = new Promise((resolve, reject) => {
	// throw '出现错误' // 抛出错误处理
	
	// resolved状态
	// resolve(100);
	
	// pending状态
	setTimeout(() => {
		resolve(100); // 函数存起来
		// reject('失败hh')
	}, 1000);
	
	// rejected状态
	
	// reject('失败')
}).then(data => { // then() 方法 参数成功回调函数,失败回调函数
	console.log('第一个成功', data); // undefined
	// return data // 100
	
	// return p // 返回自己死循环
	
	// return new OtherPromise((resolve) => {
	// 	resolve('别人的promise')
	// })
	
	// 需要递归去处理
	// return new Promise((resolve, reject) => {
	// 	resolve(new Promise((resolve, reject) => {
	// 		resolve(data);
	// 	}))
	// })
}, reason => {
	console.log('第一个失败', reason);
	// return reason;
	throw '错误错误'
}).then(data => { // then() 方法 参数成功回调,失败回调 // promise 才能调用then
	console.log('第二个promise成功', data);
}, reason => {
	console.log('第二个promise失败', reason);
})

复制代码
const PENDING = 'pending';
const RESOLVED = 'resolved';
const REJECTED = 'rejected';
class Promise {
	constructor(executor) {
	    // console.log('我的promise');
		this.status = PENDING;
		this.value = null;
		this.reason = null;
		this.resolveCallbacks = []; // 存函数
		this.rejectCallbacks = [];
		// new Promise((resolve, reject) => {})
		try{
			executor(this.resolve.bind(this), this.reject.bind(this));
		}catch(e){
			//TODO handle the exception
			this.reject(e)
		}
	}
	// resolve() 函数
	resolve(value) {
		// 调用 resolve的时候,状态 resolved
		if(this.status === PENDING) {
			this.value = value;
			this.status = RESOLVED;
			this.resolveCallbacks.forEach(onFulfilled => {
				onFulfilled();
			})
		}
	}
	// reject()
	reject(reason) {
		// 调用 reject的时候,状态 rejected
		if(this.status === PENDING) {
			this.reason = reason;
			this.status = REJECTED;
			this.rejectCallbacks.forEach(onRejected => {
				onRejected();
			})
		}
	}
	then(onFulfilled, onRejected) {
		// 链表 onFulfilled onRejected 这两个可以都不传
		// 透传现象
		onFulfilled = typeof onFulfilled === 'function'  ? onFulfilled : data => data;
		onRejected = typeof onRejected === 'function' ? onRejected : err => { throw err };
		// then().then(参数)
		// console.log('then状态', this.status);
		let promise2 = new Promise((resolve, reject) => {
			if (this.status === PENDING) {
				// this.resolveCallbacks.push(onFulfilled);
				this.resolveCallbacks.push(() => {
					setTimeout(() => {
						// console.log('外面执行完', promise2)
						try{
							let x = onFulfilled(this.value);
							// 解析promise 判断是不是死循环, return Promise
							resolvePromise(x, promise2, resolve, reject);
						}catch(e){
							//TODO handle the exception
							// 如果报错的话,就当你失败
							reject(e)
						}
					});
				})
				this.rejectCallbacks.push(() => {
					setTimeout(() => {
						// console.log('外面执行完', promise2)
						try{
							let x = onRejected(this.reason);
							// 解析promise 判断是不是死循环, return Promise
							resolvePromise(x, promise2, resolve, reject);
						}catch(e){
							//TODO handle the exception
							// 如果报错的话,就当你失败
							reject(e);
						}
					});
				});
			}
			if (this.status === RESOLVED) {
				setTimeout(() => {
					// console.log('外面执行完', promise2)
					try{
						let x = onFulfilled(this.value);
						// 解析promise 判断是不是死循环, return Promise
						resolvePromise(x, promise2, resolve, reject);
					}catch(e){
						//TODO handle the exception
						// 如果报错的话,就当你失败
						reject(e)
					}
				});
			}
			if (this.status === REJECTED) {
				setTimeout(() => {
					// console.log('外面执行完', promise2)
					try{
						let x = onRejected(this.reason);
						// 解析promise 判断是不是死循环, return Promise
						resolvePromise(x, promise2, resolve, reject);
					}catch(e){
						//TODO handle the exception
						// 如果报错的话,就当你失败
						reject(e);
					}
				});
			}
		})
		return promise2;
	}
}

function resolvePromise(x, promise2, resolve, reject) {
	// 调用第一个Promise是我们的promise,第二个就不一定了。
	if (x === promise2) {
		return reject(new TypeError('Chaining cycle detected for permise!'));
	}
	// 如何判断它是promise
	// promise is an object or function with a then method whose behavior conforms to this specification.
	if (x && (typeof x === 'object' || typeof x === 'function')) {
		// 有没有调过
		let called;
		try{
			let then = x.then; // Object.defineProperty
			// 如果不是function调用会报错
			if (typeof then === 'function') {
				then.call(x, value => {
					if (called) return;
					called = true;
					
					resolvePromise(value, promise2, resolve, reject);
				}, reason => {
					if (called) return;
					called = true;
					reject(reason);
				}) // x.then
			} else {
				// 当成普通值
				resolve(x)
			}
		}catch(e){
			if (called) return;
			called = true;
			//TODO handle the exception
			reject(e); // 就算是promise不管
		}
	} else {
		resolve(x);
	}
}

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

var promisesAplusTests = require('promises-aplus-tests');

promisesAplusTests(Promise, function(err) {
	console.log('测试用例调用失败', err);
})

module.exports = Promise

// 
复制代码

https://github.com/webVueBlog/Leetcode

通过了官方的872个测试用例。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
引用\[1\]中提到了在回调函数中返回一个pending状态的promise对象的方法,这是因为在promise链中,执行then方法的成功或失败回调取决于上一个promise的状态。如果中间返回一个初始状态的promise对象,then方法无法确定执行哪个回调,后续的then方法也不会执行,导致promise链中断。 引用\[2\]中提到了手写Promise的方法。为了实现链式调用,我们需要在第一个then方法中返回一个新的promise对象。根据官方规定,我们可以在then方法中创建一个新的promise对象,并将其命名为promise2。然后,我们可以将promise2返回的值传递给下一个then方法。如果返回的是一个普通值,则将该值传递给下一个then方法。 引用\[3\]中给出了一个基本的Promise实现的示例代码。首先,我们使用class关键字声明一个Promise类,并在构造函数中传入一个参数(executor函数)。executor函数有两个参数,resolve和reject,分别表示成功和失败。在executor函数中,我们可以执行异步操作,并在适当的时候调用resolve或reject来改变Promise的状态。根据官方规定,Promise存在三个状态:pending(等待态)、fulfilled(成功态)和rejected(失败态)。成功时,Promise的状态不可再次改变,并且需要有一个不可改变的值。失败时,Promise的状态也不可再次改变,并且需要有一个不可改变的原因。如果executor函数报错,直接执行reject()。 综上所述,手写Promise实现需要注意返回一个新的promise对象,并在适当的时候调用resolve或reject来改变Promise的状态。 #### 引用[.reference_title] - *1* *2* *3* [Promise学习笔记(尚硅谷)](https://blog.csdn.net/Ch_ensf/article/details/124699879)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值