当前位置:网站首页>JS to implement a promise of promises/a+ specification
JS to implement a promise of promises/a+ specification
2022-07-24 16:37:00 【My_ Bells】
1. Code implementation
// promise Three states
const PENDING = 'pending';
const FULFILLED = 'fulfilled';
const REJECTED ='rejected';
class Promisex {
constructor(fn){
if(typeof fn !== 'function') throw new Error('Promisex must accept a function')
this.state = PENDING;// The initial state
this.value = null;// Information returned / Reasons for rejection
this.onFulfilledQueues = [];// Storage fulfilled States correspond to onFulfilled Function queue
this.onRejectedQueues = [];// Storage rejected States correspond to onRejected Function queue
// value The final value received in the success state
const resolve=(value) => {
if(value instanceof Promisex){
return value.then(resolve,reject);
}else{
// Add setTimeout reason :
// In practice, make sure that onFulfilled and onRejected Method is executed asynchronously ,
setTimeout(() => {
if(this.state!==PENDING) return;
this.state = FULFILLED;
this.value = value;
let cb;
while (cb = this.onFulfilledQueues.shift()) {
cb(value)
}
});
}
}
// reason Rejection in failure state
const reject=(reason)=>{
setTimeout(() => {
if(this.state!==PENDING) return;
this.state = REJECTED;
this.value = reason;
let cb;
while (cb = this.onRejectedQueues.shift()) {
cb(reason)
}
});
}
// perform
try {
fn(resolve,reject)
} catch (error) {
reject(error)
}
}
// register fulfilled state /rejected The callback function corresponding to the State
//then Back to a new promise object
//then Three states need to be handled in
then(onFulfilled, onRejected){
onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : value => value;
onRejected = typeof onRejected === 'function' ? onRejected : reason => {
throw reason; };
let newPromise;
if(this.state===FULFILLED){
// Success status
return newPromise=new Promisex((resolve,reject)=>{
setTimeout(() => {
try {
let x=onFulfilled(this.value);//onFulfilled There is a return value
resolvePromise(newPromise,x,resolve,reject);
} catch (e) {
reject(e)
}
});
})
}
if(this.state===REJECTED){
// Failure status
return newPromise=new Promisex((resolve,reject)=>{
setTimeout(() => {
try {
// Regardless of promise1 By reject Or was resolve when promise2 Will be resolve, Only when there is an exception will it be rejected.
let x=onRejected(this.value);//onRejected There is a return value
resolvePromise(newPromise,x,resolve,reject);
} catch (e) {
reject(e)
}
});
})
}
if(this.state===PENDING){
// Wait state
// take onFulfilled/onRejected Collect and stage in the queue
return newPromise=new Promisex((resolve,reject)=>{
this.onFulfilledQueues.push((value)=>{
try {
let x=onFulfilled(value);
resolvePromise(newPromise,x,resolve,reject);
} catch (e) {
reject(e)
}
})
this.onRejectedQueues.push((reason)=>{
try {
let x=onRejected(reason);
resolvePromise(newPromise,x,resolve,reject);
} catch (e) {
reject(e);
}
})
})
}
}
catch(onRejected){
return this.then(undefined,onRejected);
}
finally(cb){
return this.then(value=>{
Promisex.resolve(cb()).then(()=>value)
},err=>{
Promisex.resolve(cb()).then(()=>{
throw err})
})
}
static resolve(value){
if(value instanceof Promisex) return value;
return new Promisex(resolve=>resolve(value));
}
static reject(reason){
return new Promisex((undefined,reject)=>reject(reason));
}
static all(list){
return new Promisex((resolve,reject)=>{
let values=[];
let count=0;
for(let [i,p] of list.entries()){
this.resolve(p).then(res=>{
values[i]=res;
count++;
if(count === list.length) resolve(values);
},err=>{
reject(err);
})
}
})
}
static race(list){
return new Promisex((resolve,reject)=>{
for(let p of list){
this.resolve(p).then(res=>{
resolve(res);
},err=>{
reject(err);
})
}
})
}
}
function resolvePromise(promise2,x,resolve,reject){
if(promise2===x){
// If from onFulfilled In return x Namely promise2 It will result in a circular quotation error
return reject(new TypeError(' Circular reference '))
}
let called = false;// Avoid multiple calls
// * 1.promise object
// * 2.thenable object / function
// * 3. Common value
if(x instanceof Promisex){
if(x.state===PENDING){
x.then(y=>{
resolvePromise(promise2,y,resolve,reject);
},reason=>{
reject(reason)
})
}else{
x.then(resolve,reject);
}
}else if(x&&(typeof x==='object'||typeof x==='function')){
try {
// Whether it is thenable object ( have then Object of method / function )
let then = x.then;
if(typeof then==='function'){
then.call(x,y=>{
if(called)return;
called=true;
resolvePromise(promise2,y,resolve,reject);
},reason=>{
if(called)return;
called=true;
reject(reason);
})
}else{
// Description is a common object
resolve(x)
}
} catch (e) {
if(called)return;
called=true;
reject(e)
}
}else{
resolve(x);
}
}
// Use promises-aplus-tests test
Promisex.deferred = function() {
// Delay object
let defer = {
};
defer.promise = new Promisex((resolve, reject) => {
defer.resolve = resolve;
defer.reject = reject;
});
return defer;
};
module.exports = Promisex;
Finally, execute promises-aplus-tests ./xxx.js To test
2. Example
// Regardless of promise1 By reject Or was resolve when promise2 Will be resolve, Only when there is an exception will it be rejected.
new Promisex((resolve, reject)=>{
setTimeout(() => {
reject(2)
}, 2000);
}).then(res=>{
console.log(res);
return res+1;
},e=>{
return e;//2
}).then(res=>{
console.log(res)//2
},e=>{
return e;
})
3. Reference resources
Promise Detailed explanation and Implementation (Promise/A+ standard )
Promises/A+ standard ( english )
【 translate 】Promises/A+ standard
Javascript Asynchronous programming 4 Methods
边栏推荐
- Complete guide on how to prevent cross site scripting (XSS) attacks
- How to deal with the start and end times in mybatics
- VSCode如何鼠标滚轮放大界面
- Why should we launch getaverse?
- 解决Eureka默认缓存配置导致时效性问题
- To create a private Ca, I use OpenSSL
- Dongfang Guangyi refuted the rumor late at night, saying that the news that the hammer was filed for investigation was untrue!
- 会议OA项目进度(二)
- ZCMU--5023: 家庭划分(C语言)
- thinkphp3.2.5无法跳转到外部链接
猜你喜欢

Princeton calculus reader 02 Chapter 1 -- composition of functions, odd and even functions, function images

期盼已久全平台支持-开源IM项目OpenIM之uniapp更新

15. ARM embedded system: how to debug single board with PC

Duplicate content in lookup table

Template method mode

如何在 PHP 中防止 XSS
[email protected]"/>ZBar source code analysis - img_ scanner. c | [email protected]

Win10 download address

Envi grid resampling

1184. Distance between bus stops
随机推荐
【南京农业大学】考研初试复试资料分享
hping3安装使用
Jupyter uses tips
Thinkphp3.2.5 cannot jump to external links
详解 Apache Hudi Schema Evolution(模式演进)
ARP 入门
Cross server, insert, search
Envi grid resampling
After data management, the quality is still poor
Summary of experience in using.Net test framework xUnit, mstest, specflow
期盼已久全平台支持-开源IM项目OpenIM之uniapp更新
leetcode:162. 寻找峰值【二分寻找峰值】
15、ARM嵌入式系统:如何用PC调试单板
To create a private Ca, I use OpenSSL
EF data migration
随笔记:同步、异步和微任务、宏任务的打印顺序
我们为什么要推出Getaverse?
EF LINQ Miscellany
EF miscellaneous
MySQL converts strings to numeric types and sorts them