Last active
February 17, 2022 07:31
-
-
Save Ariex/e6dd7916bf0004bf18a0d62a669caf07 to your computer and use it in GitHub Desktop.
Promise.allInOrder
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
// v3 is shorter than v2, and achieve same goal | |
(()=>{ | |
let Deferred = function(){ | |
let resolver, rejector, | |
promise = new Promise((resolve, reject)=>{ | |
resolver = resolve; | |
rejector = reject; | |
}); | |
promise.resolve = d=>resolver(d); | |
promise.reject = d=>rejector(d); | |
return promise; | |
}; | |
// the idea of this function is, setup a continuous task that will be executed by each of the previous task in order. | |
// for example, if there are 3 previous tasks, task[2] finished, the continuous task will not be executed, then task[1] finished, the continuous task will be executed for task[1] then task[2] in order, then task[3] finished, the continuous task will executed for task[3] | |
Promise.allInOrder = (...promises)=>{ | |
// this thenForEachFunc could be invoked when there is no func been set, and func will be called in order immidiately when it been set with a value | |
// to achieve this, we make invoke an async function, so it will only return value when func have valid value. If func is null, then create a deferred object then push to a queue, which this queue will be processed when setFunc been called, to make sure the async invoke function will be resolved eventually. | |
let thenForEachFunc = (function(){ | |
let func = null; | |
let promiseToExecuteFunc = new Array(promises.length); | |
return { | |
setFunc: _func=>{ | |
func = _func; | |
for(let i=0,l=promiseToExecuteFunc.length;i<l;i++){ | |
if(promiseToExecuteFunc[i]===void(0)){ | |
return; | |
}else if(promiseToExecuteFunc[i]!==null){ | |
let d = promiseToExecuteFunc[i]; | |
d.resolve(func); | |
promiseToExecuteFunc[i] = null; | |
} | |
} | |
}, | |
invoke: async function(data, index){ | |
let promiseToGetResult = new Promise((resolve, reject)=>{ | |
let deferred = new Deferred(); | |
deferred.then(func=>resolve(func.call(null, ...arguments))); | |
// to make sure the callback function will be executed in order, we put it in a queue, which will be processed in order | |
// also since js is single thread, so the chance that adding a new element to queu when queue is processing is not possible, whenever calling "invoke" method, it will have to happen after previous setFunc function. | |
promiseToExecuteFunc[index]=deferred; | |
}); | |
this.setFunc(func); | |
return promiseToGetResult; | |
} | |
}; | |
})(); | |
let anotherPromise = promises.map((p, i)=>{ | |
return promises[i].then(d=>{ | |
return new Promise(async(resolve, reject)=>{ | |
let result = await thenForEachFunc.invoke(d, i); | |
resolve(result); | |
}); | |
}); | |
} | |
); | |
return { | |
thenForEach: thenForEachCallback => { | |
thenForEachFunc.setFunc(thenForEachCallback); | |
return { | |
all: func=>{ | |
Promise.all(anotherPromise).then(d=>func(d)); | |
} | |
} | |
} | |
} | |
}; | |
})(); | |
/* Promise | |
.allInOrder(promise1, promise2, promise3) | |
.thenForEach(d=>console.log(d)) | |
.catchForEach(err=>{}) //<== not support yet, but should not be hard to add | |
.all((...d)=>console.log(d)); | |
*/ | |
(()=>{ | |
let timeConsumingFunc = param=>new Promise( | |
(resolve)=>{ | |
let timeout = Math.random() * 5000; | |
console.log(`task ${param} will be resolved in ${timeout}ms`); | |
setTimeout(()=>{ | |
console.log(`${param} resolved`); | |
resolve(param+10); | |
}, timeout); | |
} | |
); | |
Promise | |
.allInOrder(timeConsumingFunc(1), timeConsumingFunc(2), timeConsumingFunc(3)) | |
.thenForEach(d=>{ | |
console.log(d); | |
return d+20; | |
}) | |
.all(ds=>{ | |
console.log(`all method called`); | |
console.log(ds); | |
}) | |
})(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment