How to combine asynchronous calls with synchronous in javascript

I'm kind of starting to learn javascript and wondering about combining synchronous and asynchronous calls with functions. This will only be a theoretical problem, but I hope that it conveys this idea.

Suppose we have a javascript program that decides how many bananas and oranges I need to buy.

console.log('buy %d bananas and %d oranges', bananas, oranges) 

Now I can decide how many bananas I can buy, but I need to ask my wife how many oranges she wants, so I set out. (I can write an async function to represent this).

This will be my immediate approach:

 var bananas = 10; var oranges = 0; textWife('askAboutOranges',function(number){ oranges = number; } console.log('buy %d bananas and %d oranges', bananas, oranges) 

But for me this does not make sense, because I have to wait until my wife answers, so I probably will not have the number of oranges on time.

Therefore, I can change my program to:

 var bananas = 10; var oranges = 0; textWife('askAboutOranges',function(number){ oranges = number; console.log('buy %d bananas and %d oranges', bananas, oranges); } 

But I do not like it, because now I have the logic of deciding what to buy, including bananas, in response from my wife. What if I decide I don’t want oranges, I need to do something like this:

 var bananas = 10; var oranges = 0; if (wantOranges) { textWife('askAboutOranges',function(number){ oranges = number; console.log('buy %d bananas and %d oranges', bananas, oranges); } } else console.log('buy %d bananas and %d oranges', bananas, oranges); 

So my question is: can someone explain to me what is the best / right way to do something like this?

+6
source share
5 answers

jQuery Deferred is a great tool for your belt. I could do something like this to separate the problems:

 function decideHowManyBananas() { return 10; } function decideHowManyOranges() { var deferred = $.Deferred(); if (wantOranges) { textWife('askAboutOranges', function(number) { deferred.resolve(number); }); } else { deferred.resolve(0); } return deferred.promise(); } $.when(decideHowManyBananas(), decideHowManyOranges()).done(function(bananas, oranges) { console.log('buy %d bananas and %d oranges', bananas, oranges); }); 
+7
source

There is no right / best way - it always depends. Modern Javascript libraries use concepts such as Deferred and w160 to synchronize between multiple asynchronous calls, synchronization calls, and instant data. Using jquery, your code can be written as:

 $.when({bananas:10, oranges:1}, textWife('askAboutOranges')).done(function(myList, herList) { buyBananas(myList.bananas); buyOranges(myList.oranges + herList.oranges); }); 

See http://api.jquery.com/category/deferred-object/ for more details.

And here's how to create pending objects in your code in an elegant way:

 function decideHowManyOranges() { if (!wantOranges) return 0; return $.Deferred(function(d) { textWife('askAboutOranges', function(number) { d.resolve(number); }) }) } numOfBananas = 10 $.when(numOfBananas, decideHowManyOranges()).done(function(bananas, oranges) { console.log('buy %d bananas and %d oranges', bananas, oranges); }); 
+3
source

With Promises

 // setup var bananas = 4 var wantOranges = true function textWife() { return new Promise((resolve, reject) => setTimeout(() => resolve(8), 1000)) } // execution Promise.all([ bananas, wantOranges ? textWife() : 0 // ternary is necessary here because boolean logs as `NaN` ]).then(([bananas, oranges]) => console.log('buy %d bananas and %d oranges', bananas, oranges)) 

Note: I use ..
Promises
Destruction purpose , where var [bananas, oranges] = [4, 8] same as var bananas = 4, oranges = 8 .
Arrow Functions () => {}

+1
source

Prepare the function and use it in both cases to remove duplicate code:

 var bananas = 10; var oranges = 0; function buyStuff() { console.log('buy %d bananas and %d oranges', bananas, oranges); } if (wantOranges) textWife('askAboutOranges',function(number){ oranges = number; buyStuff(); }) else buyStuff(); 
0
source

In the first example, you state that the answer to the question "how many bananas and oranges should I buy?" depends on both the information you have, that is, on the number of necessary bananas, as well as on the information that you do not have, the number of necessary oranges, so you cannot answer it without first receiving the missing information.

Then you reorganize your code to postpone the answer to your question until you get the missing information, which is a typical approach to solving this kind of dependency.

Then you indicate that this does not satisfy you, because you may not buy any oranges at all. This is a new requirement and therefore annul your initial question, changing it to "how many bananas should I buy?"

By changing the requirement for missing information, you change the question, so you need to ask a specific case for two problems.

The last example code that you provide does this by first deciding whether you need to buy both bananas and oranges or just oranges, which is really the easiest way to solve your problem.

0
source

Source: https://habr.com/ru/post/949059/


All Articles