Skip to content

Instantly share code, notes, and snippets.

@xxMrPHDxx
Created December 3, 2019 07:48
Show Gist options
  • Save xxMrPHDxx/bfa819c4584fe3e44e2098d6d3a6ec5e to your computer and use it in GitHub Desktop.
Save xxMrPHDxx/bfa819c4584fe3e44e2098d6d3a6ec5e to your computer and use it in GitHub Desktop.
Custom Promise
class HttpResponse{
constructor(status, statusText, body, headers={}){
this.status = status;
this.statusText = statusText;
this.body = body;
this.headers = headers;
}
}
function fetch(url, options={}){
const method = 'method' in options ? options['method'] : 'GET';
const headers = 'headers' in options ? options['headers'] : {};
const body = 'body' in options ? options['body'] : '';
return new Promise((resolve, reject)=>{
const req = new XMLHttpRequest();
req.open(method, url);
req.send(body);
req.onreadystatechange = ()=>{
if(req.readyState === 4){
if(req.status === 200){
const headers = {};
for(let header of req.getAllResponseHeaders().split(/\n/g)){
const [key, value] = header.split(': ');
headers[key] = value;
}
resolve(new HttpResponse(200, req.statusText, req.responseText, headers));
}else{
reject(`HttpError ${req.status}: ${req.statusText}`);
}
}
}
});
}
class Promise {
constructor(action){
this.status = 'pending';
this.value = this.error = undefined;
action((value=>{
this.status = 'resolved';
this.value = value;
}).bind(this),(error=>{
this.status = 'rejected';
this.error = error;
}).bind(this));
}
then(callback){
return new Promise((resolve, reject)=>{
const timer = setInterval((()=>{
if(this.status !== 'pending'){
try{
if(this.status === 'resolved') resolve(callback(this.value));
else if(this.status === 'rejected') reject(this.error);
}catch(e){
reject(e);
}finally{
clearInterval(timer);
}
}
}).bind(this), 33)
});
}
catch(callback){
return new Promise((resolve, reject)=>{
const timer = setInterval((()=>{
if(this.status !== 'pending'){
if(this.status === 'resolved'){
resolve(this.value)
}else if(this.status === 'rejected'){
reject(this.error);
callback(this.error);
}
clearInterval(timer);
}
}).bind(this));
});
}
finally(callback){
return new Promise((resolve, reject)=>{
const timer = setInterval((()=>{
if(this.status !== 'pending'){
(this.status === 'resolved' ? resolve : reject)(this.status === 'resolved' ? this.value : this.error);
callback(this.status === 'resolved' ? this.value : this.error);
clearInterval(timer);
}
}).bind(this), 33);
});
}
static resolve(value){
if(value instanceof Promise){
return new Promise((resolve, reject)=>{
const timer = setInterval((()=>{
if(value.status !== 'pending'){
if(value.status === 'resolved') resolve(value.value);
else if(value.status === 'rejected') reject(value.error);
clearInterval(timer);
}
}).bind(this))
})
}
return new Promise((resolve, reject)=>resolve(value));
}
static all(array){
return new Promise((resolve, reject)=>{
const results = [];
for(const item of array){
results.push(Promise.resolve(item));
}
const timer = setInterval((()=>{
for(const promise of results){
if(promise.status === 'pending') return;
if(promise.status === 'rejected') reject(promise.error);
}
resolve(results.map(result=>result.value));
}).bind(this), 33);
});
}
}
function log_return(value){ console.log(value); return value; }
Promise.resolve(new Promise((resolve, reject)=>{
setTimeout(()=>{resolve(100)}, 1000);
}))
.then(log_return)
.then(val => val*2)
.catch(error => console.log('Nothing wrong here!'))
.finally(val => {console.log('Do nothing', val); return val;})
.then(log_return)
.then(val => {
throw 'Invalid transaction!';
})
.catch(error => {alert(error); return error;})
.finally(val => {console.log('Clearing transaction:', val);})
Promise.all([1, 2, 3, 4])
.then(console.log)
Promise.all([
new Promise((resolve, reject)=>setTimeout(()=>resolve('Item A'), 1000)),
new Promise((resolve, reject)=>setTimeout(()=>resolve('Item B'), 2000)),
new Promise((resolve, reject)=>setTimeout(()=>resolve('Item C'), 3000))
])
.then(console.log)
fetch('Promise.js')
.then(res=>res.json())
.catch(()=>{})
.then(console.log)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment