Iterating Javascript Object Synchronously
Solution 1:
The following will do what you ask, it returns an array of resolve values.
Do you want to stop processing if any one of them rejects? In case you need to make some changes, now it rejects if any of them reject and won't continue processing they keys in your object (object named myObject
):
var myObject = {
'one': ["one"],
'two': ["two"]
};
var doStuff = arr =>
console.log("starting:", arr[0]) ||
Promise.resolve(arr[0]);
var [promise,result] =
Object.keys(myObject)
.reduce(
([promise,results], key) =>
[
promise
.then(
resolve =>
doStuff(myObject[key])
)
.then(
resolve => results.push(resolve)&&resolve
)
.then(
resolve => console.log("done:", resolve)
)
,results
]
, [Promise.resolve(), []]
)
promise.then(
_ => {
console.log("done all",result)
}
);
The answer ayushgp uses recursion, here is a working example that doesn't need changes to doSomething:
var myObject = {
'one': ["one"],
'two': ["two"]
};
var doStuff = arr =>
console.log("starting:",arr[0]) ||
Promise.resolve(arr[0])
var process = (arr,processFn) => {
const rec = (arr,processFn,promise,results) =>
arr.length === 0
? promise.then(_=>results)
: promise
.then(_ => processFn(arr[0][1]))
.then(result=>results.push(result)&&console.log("resolved:",result))
.then(_ => rec(arr.slice(1),processFn,promise,results));
return rec(arr,processFn,Promise.resolve(),[]);
};
process(
Object.keys(myObject).map(key=>[key,myObject[key]]),
doStuff
)
.then(
results => console.log("done all, results:",results)
);
Solution 2:
One solution would be to make doStuff
return a Promise
which you can use to build a chain of promises using calls to then
.
The Bluebird promise library provides this functionality with .each
and .mapSeries
.
You could implement it as:
Promise.forEachSeries = function(array, action) {
return array.reduce(function(prevPromise, value, index, array) {
return prevPromise.then(function() {
return action(value, index, array);
});
}, Promise.resolve());
}
You would use it like this:
Promise.forEachSeries(arr, doStuff);
Solution 3:
You could use the solution you proposed at the end using Object.entries(obj)
. For example,
let arrProps = Object.entries(myObject);
process(index) {
if (index < arrProps.length){
// Call the callback once you complete execution of doStuff
doStuff(arrProps[index], () => process(index + 1));
}
}
Inside doStuff:
function doStuff(props, callback) {
// Process props
//finally in the promise of async call, on success call
.then(callback)
}
OR you could use a generator function, if you want to use for ... in
loop.
Solution 4:
The Promise object represents the eventual completion (or failure) of an asynchronous operation, and its resulting value. you can try like .
$("#myPara").delay(4500).fadeOut().promise().done(function(){
$("#myHeading").attr("style","display:none;") ;
for(var i=10;i<15;i++){
console.log(i);
}
});
console.log("Hello promise !");
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<p id="myPara"> Hello </p>
<h1 id="myHeading">to be hide</h1>
for (let prop in myObject) {
if (myObject.hasOwnProperty(prop)) {
var stuff= doStuff(prop, myObject[prop]).promise().done(function(){
// Do whatever u want after completion of doStuff
});
}
}
Post a Comment for "Iterating Javascript Object Synchronously"