Home Synchronous way of handling asynchronous function, two level deep
Reply: 2

Synchronous way of handling asynchronous function, two level deep

Sujit Kumar Singh
1#
Sujit Kumar Singh Published in 2017-12-07 10:52:52Z

I am looping over an array to update its values using returned value from called function which internally calls an asynchronous function.

I need to handle asynchronous function in synchronous way which is not being directly called. This is replication of scenario.

function condition(){
    // Code of this function is not accessible to me.
    return new Promise(function(resolve, reject){
        setTimeout(function(){
            if(parseInt(Math.random() * 100) % 2){
                resolve(true);
            }
            else{
                reject(false)
            }
        }, 1000)
    });
}

async function delayIncrease(value){
    var choice = await condition(); 

    if(choice) { return ++value; }
    else { return --value; }
}

// Start calling functions
dataArr = [1,2,3,4,5];
for(var i in dataArr){
    dataArr[i] = delayIncrease(dataArr[i]);
}

If possible, I would like to have the solution in above structure mentioned.

I have achieved the desired result by adding other function and passing "index" + "new_value" as parameters. This function directly modifies original array and produces desired result. Working example.

function condition(){
    // Code of this function is not accessible to me.
    return new Promise(function(resolve, reject){
        setTimeout(function(){
            if(parseInt(Math.random() * 100) % 2){
                resolve(true);
            }
            else{
                reject(false)
            }
        }, 1000)
    });
}

function delayIncrease(value, index){            
    condition().then(
        function(){ updateData(++value, index) },
        function(){ updateData(--value, index) }
    )
}

function updateData(value, index){
    dataArr[index] = value;          
}

dataArr = [1,2,3,4,5];
for(var i in dataArr){
    dataArr[i] = delayIncrease(dataArr[i], i);
}

Please provide solution for this requirement in best possible way. Possible solution in Angular 4 way is also appriciated. I thought of writing it in normal JavaScript form as Observables behave nearly same.

I followed this Medium page and http://exploringjs.com

HMR
2#
HMR Reply to 2017-12-07 12:36:55Z

You could do something like this:

var condition = async () =>
  (parseInt(Math.random() * 100) % 2)
    ? true
    : false

var delayIncrease =  async (value) =>
  (await condition())
    ? ++value
    : --value

var dataArr = [1, 2, 3, 4, 5];
// Start calling functions
Promise.all(
  dataArr.map(
    delayIncrease
  )
)
.then(
  resolve => console.log("results:",resolve)
  ,reject => console.warn("rejected:",reject)
)

Once something is async you have to make the entire call stack prior to that function async. If a function calls an async function that that function returns an async value and so does the one calling it and calling it and calling it ...

More info on javascript async and why can be found here.

Since the example provided doesn't have any async api's in there you don't need to do it async:

var condition = () =>
  (parseInt(Math.random() * 100) % 2)
    ? true
    : false

var delayIncrease =  (value) =>
  (condition())
    ? ++value
    : --value

var dataArr = [1, 2, 3, 4, 5];
// Start calling functions
dataArr.map(
  delayIncrease
)

[update]

When you mutate an array of objects and cosole.log it you may not see the values as they actually were when you log it but you see the values as they are right now (this is a "bug" in console.log).

Consider the following:

var i = -1,arr=[];
while(++i<1){
  arr[i]={};
  arr[i]["name"+i]=i
}

var process = (index) =>
  arr[index]["name"+index]++;

arr.forEach(
  (item,index) =>
    Promise.resolve(index)
    .then(process)
);
console.log("obj at the moment you are looking at it:",arr)
console.log("obj at the moment it is logged:",JSON.stringify(arr))

When you expand obj at the moment you are looking at it you see that name0 property of the first element changed to 1.

However; look at obj at the moment it is logged: and see the actual value of the first element in the array. It has name0 of 0.

You may think that the that code runs asynchronous functions in a synchronous way by mutating the object(s) in an array, but you actually experience a "bug" in console.log

Bergi
3#
Bergi Reply to 2017-12-07 12:06:03Z

Your condition function does not really fulfill the promise with either true or false, it does randomly fulfill or reject the promise. Instead of branching on a boolean, you will need to catch that "error":

async function delayIncrease(value) {
    try {
        await condition(); 
        return ++value;
    } catch(e) {
        return --value;
    }
}
You need to login account before you can post.

About| Privacy statement| Terms of Service| Advertising| Contact us| Help| Sitemap|
Processed in 0.41111 second(s) , Gzip On .

© 2016 Powered by mzan.com design MATCHINFO