Last active
March 15, 2019 09:51
-
-
Save nfroidure/5697689 to your computer and use it in GitHub Desktop.
A simple Promise implementation. Moved to GitHub : https://github.com/nfroidure/Promise/blob/master/Promise.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var Promise=(function() { | |
var AWAIT=0, SUCCESS=1, FAIL=-1; | |
function Promise(logic) { | |
var promise=this; | |
promise.solved=AWAIT; | |
var success=function (value) { | |
if(AWAIT!==promise.solved) | |
return; | |
promise.solved=SUCCESS; | |
promise.value=value; | |
if(promise.successCallback) | |
promise.successCallback(value); | |
}; | |
var fail=function (error) { | |
if(AWAIT!==promise.solved) | |
return; | |
promise.solved=FAIL; | |
promise.error=error; | |
if(promise.failCallback) | |
promise.failCallback(error); | |
}; | |
var progress=function (value) { | |
if(AWAIT!==promise.solved) | |
return; | |
if(promise.progressCallback) | |
promise.progressCallback(error); | |
}; | |
promise.dispose=logic(success, fail, progress); | |
} | |
Promise.prototype.then = function(success, fail, progress) { | |
var thenSuccess, thenFail, thenProgress, returnValue, promise=this; | |
var thenPromise=new Promise(function(success,fail,progress) { | |
thenSuccess=success; | |
thenFail=fail; | |
thenProgress=progress; | |
}); | |
var successLogic=function() { | |
if(success) | |
returnValue=success(promise.value); | |
if(returnValue instanceof Promise) { | |
returnValue.then(thenSuccess, thenFail, thenProgress); | |
} else { | |
thenSuccess(returnValue); | |
} | |
}; | |
var failLogic=function() { | |
if(fail) | |
returnValue=fail(promise.error); | |
thenFail&&thenFail(returnValue.error); | |
}; | |
if(AWAIT===this.solved) { | |
this.successCallback=successLogic; | |
this.failCallback=failLogic; | |
this.progressCallback=progress; | |
} else if(SUCCESS===this.solved) { | |
setTimeout(successLogic,0); | |
} else { | |
setTimeout(failLogic,0); | |
} | |
return thenPromise; | |
}; | |
Promise.all=function () { | |
var promises=Array.prototype.slice.call(arguments,0), | |
solved=0, | |
returnValues=new Array(promises.length); | |
return new Promise(function(successCallback,errorCallback) { | |
var promiseDispose=function() { | |
promises.forEach(function(p) { | |
AWAIT===p.solved&&p.dispose&&p.dispose(); | |
}); | |
}; | |
var promiseSuccess=function(promise,index) { | |
return function(value) { | |
if(solved<promises.length) { | |
returnValues[index]=value; | |
solved++; | |
if(solved==promises.length) | |
successCallback(returnValues); | |
} | |
} | |
}; | |
var promiseError=function(promise,index) { | |
return function(error) { | |
if(solved<promises.length) { | |
errorCallback(error); | |
solved=promises.length; | |
} | |
} | |
}; | |
promises.forEach(function(promise,index){ | |
promise.then(promiseSuccess(promise,index), | |
promiseError(promise,index)); | |
}); | |
return promiseDispose; | |
}); | |
}; | |
Promise.any=function () { | |
var promises=Array.prototype.slice.call(arguments,0); | |
var errors=0; | |
return new Promise(function(successCallback,errorCallback) { | |
var promiseDispose=function() { | |
promises.forEach(function(p) { | |
AWAIT===p.solved&&p.dispose&&p.dispose(); | |
}); | |
}; | |
var promiseSuccess=function(value) { | |
successCallback(value); | |
promiseDispose(); | |
}; | |
var promiseError=function(error) { | |
if(++errors===promises.length) | |
errorCallback(error); | |
}; | |
promises.forEach(function(promise,index){ | |
promise.then(promiseSuccess,promiseError); | |
}); | |
return promiseDispose; | |
}); | |
}; | |
return Promise; | |
})(); | |
// Simple tests | |
// sync resolution | |
var p=new Promise(function myPromiseLogic(success, error, progress) { | |
success(1); | |
}).then(function(value){ | |
return value+1; | |
}).then(function(value) { | |
console.log(value); | |
}); | |
// output : 2 | |
// async resolution | |
var p=new Promise(function myPromiseLogic(success, error, progress) { | |
setTimeout(function() { success(1); },0); | |
}).then(function(value){ | |
return value+1; | |
}).then(function(value) { | |
console.log(value); | |
}); | |
// output : 2 | |
// return promise | |
var p=new Promise(function myPromiseLogic(success,error,progress) { | |
success(1); | |
}).then(function(value){ | |
return new Promise(function myPromiseLogic(success,error,progress) { | |
success(value+1); | |
}); | |
}).then(function(value) { | |
console.log(value); | |
}); | |
// output : 2 | |
// Event promise generator | |
function getEventPromise(type, element, capture, iterations) { | |
iterations=iterations||1; | |
return new Promise(function(success,error) { | |
var eventHandler=function(event) { | |
iterations--; | |
if(iterations<1) { | |
success(event); | |
dispose(); | |
} | |
}; | |
var dispose=function() { | |
element.removeEventListener(type, eventHandler, capture); | |
}; | |
element.addEventListener(type, eventHandler, capture); | |
return dispose; | |
}); | |
} | |
// USAGE | |
// Simple event promise | |
getEventPromise('click',document).then(function () { | |
console.log('Clicked'); | |
}); | |
// Chaining | |
getEventPromise('keydown',document).then(function () { | |
return getEventPromise('click',document,false,2); | |
}).then(function () { | |
return getEventPromise('mousemove',document); | |
}).then(function () { | |
console.log('Keydown + click twice + mousemove sequentially') | |
}); | |
// All | |
Promise.all( | |
getEventPromise('click',document), | |
getEventPromise('keyup',document), | |
getEventPromise('mousemove',document) | |
).then(function() { | |
console.log('Keyup + click + mousemove') | |
}); | |
// Any | |
Promise.any( | |
getEventPromise('click',document), | |
getEventPromise('keyup',document), | |
getEventPromise('mousemove',document) | |
).then(function() { | |
console.log('Keyup | click | mousemove') | |
}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment