How to call a rest web service in a synchronous way?


#1

Hi,
I’d like to call a web service in a synchronous way.

I’ve tried in this way.
I’ve a class with the method fetchPingData that returns a Promise containing the data I need:

async function getSystemStatus() {
	  let wsManager = require ('../wsmanager').wsManager;
	  let myresult= await wsManager.fetchPingData();
	  console.log("resultA: ", myresult.data.result);
	  return myresult.data.result;
	}
let resultB = getSystemStatus();
console.log("resultB: ", resultB);

When I run this code in a render page I have this output:

resultB: Promise...
resultA: 0

I want that the function getSystemStatus returns a value (0 in this case) and not a Promise.
Is it possible?
It seems that the await directive does not work.
How should it be used?

Thank you

cdl


#2

Why? What do you want to have happen after the request?

Async functions were invented for the purpose of making things like web requests without tying up your whole program until you get the response. If you want to pause the whole execution of your program for however many milliseconds (or longer if the Internet is shoddy), then I’m sure there is a way. I don’t know how, because I’ve never tried to do it. However, if you just want to complete a certain function after the Promise is returned, you just need to use its methods to set up the order of operations. The important thing here is that every Promise has a then() method, which takes instructions about what needs to happen after the Promise has resolved.

async function getSystemStatus() {
	  let wsManager = require ('../wsmanager').wsManager;
	  let myresult= await wsManager.fetchPingData();
	  console.log("resultA: ", myresult.data.result);
	  return myresult.data.result;
	}
let output = getSystemStatus().then( (resultB) => console.log("resultB: ", resultB))

#3

Thank you for your answer.
With this method I can understand if the remote web services are accessible.
If not it makes no sense to go on and to call other web services.

Surely I could have done the same thing with asynchronous functions, but I think that in this case it is simpler to use a synchronous one.

I don’t know well the sytax of the Promises, but I suppose that “resultB” is assigned to “output” when the response is ready.

thank you

cld


#4

I think it’s simpler to use async functions and learn Promises, instead of trying to figure out what syntax you would need to write a synchronous request. I and most people with some modern JS experience can help you with the first one, but not the second, so if both require learning something new it’s easier to go for the path where you can get advice and code review.


#5

I use javascript Promises often, but I never used the async function declaration nor the await operator, so I was curious to understand both of them, and when I was trying them I realized something (somebody correct me if I am wrong):

  • the await operator waits for the promise to return the value
  • the async function declaration makes sure that getSystemStatus WILL ALWAYS return an AsyncFunction, so technically you are using an implicit Promise in it, no matter what you do inside

This has some interesting effects:

  • await wsManager.fetchPingData() does stop getSystemStatus until it is ready, and when it does, it returns the value
  • async function getSystemStatus is automatically converted in a Promise due the async delcaration. This has as side effect that, no matter what you do in getSystemStatus, you will have to use a “then” to get the value you place in the return, and also, that, as it has become a Promise, the execution of getSystemStatus will “wait” until the system has “time” to check it request, so, even if you dont apply an async method inside of it, there is no guarantee that it will execute before “console.log(“resultB”)”
  • await can’t be used outside an "async function"

So it seems, no matter what, using async ensures that a promise will be return one way or another (it works just to make a synchronous call INSIDE the async function), so for all purposes, your code is equivalent to this one:

let wsManager = require ('../wsmanager').wsManager;
let result B = wsManager.fetchPingData()
                        .then(res => console.log("resultA: ", res))

console.log("resultB: ", resultB);

If it were another programming language and you really needed how to synchronous function out of an asynchronous one, I would say to use a promise and block the execution through an infinite loop until the promise returns its value… however, it wont work, the promise will never finish its execution because the loop will block all the process (even if the promises seem concurrent, there is not really parallelism in JavaScript, they merely wait for the “sync code to execute” and then try to execute the async code, so loop based polling are noneffective).

So my recommendation is to use the Promise flux to disable from your program any interaction/activity from the user until the program is ready, in this fashion:

let wsManager = require ('../wsmanager').wsManager;
disableAllFunctionality()
let result B = wsManager.fetchPingData()
                        .then(res => activateAllFunctionality)

#6

Your considerations are very useful, thank you very much.