-1

First of all, I'm aware this is not a good approach, need it as temporary solution for certain functions to return value, not promise. I know it's really not good permanent solution at all, but I need it for now.

What worries me, fetch sure finishes sooner - but it runs until the whiles times out, and then to console comes first the RETVAL false, and only then second line comes RETFETCH: {....} with returned json values - it seems the 'haveResponse' value does not change in the second 'then' - but can't see why, and how to bypass it.

It's a temporary workaround for old sync fns to read some data from remote service running on local pc on some port, but for now I can't rewrite the function which expects to receive data from this fn, so there must be no promise on the outside, need to wait for response and then return it.

function syncFetch(url) {
        var haveResponse = false;
        var reqtime = new Date();
        try{
          fetch(url, {
            headers: {'Content-Type': 'application/json'},
            method: 'POST',
            timeout: 1500,
            body: JSON.stringify({cmd:'init'})
          })
          .then(response => response.json())
          .then(data => {
            console.log('RETFETCH:', data);
            haveResponse = data;
            return data;
          });
    
          // timeout
          while (haveResponse === false) {
            var endDate = new Date();
            if (haveResponse !== false) { return haveResponse; }
            if ((endDate - reqtime)/1000 > 5) { // max 5 sec
              return haveResponse;
            }
          }
          return haveResponse;
        } catch(e){ 
          console.log('error', e); 
          haveResponse = -1;
        }
       return haveResponse;
}
console.log('RETVAL',syncFetch('http://127.0.0.1:3333/'));
halfer
  • 19,824
  • 17
  • 99
  • 186
Peminator
  • 783
  • 1
  • 9
  • 24
  • Your url is malformed: `1270.0.1` – MauriceNino Jun 28 '21 at 08:01
  • Also your while loop is a bit weird and duplicates logic – MauriceNino Jun 28 '21 at 08:02
  • 1
    I didn't even know something like that is possible. AFAIK JavaScript is single threaded and it stays in a function until the function returns. It won't execute the callbacks in `then` even if you wait for hours. –  Jun 28 '21 at 08:04
  • Also, try and have your variables use the same type, i.e. I can see that `haveResponse` can either be a boolean (`false`), a number (`-1`), or an object (`data`) – andy mccullough Jun 28 '21 at 08:05
  • @MauriceNino yes sorry typo, real url is valid... – Peminator Jun 28 '21 at 08:05
  • 2
    `async` and `await` are your friends – PA. Jun 28 '21 at 08:07
  • @andymccullough yes temporary just trying to see what comes out, to identify it, but still i always receive - after timeout- the false value - coming from the line wher eit check the timeout time within the :while: loop :( – Peminator Jun 28 '21 at 08:08
  • _"Each message is processed completely before any other message is processed. This offers some nice properties when reasoning about your program, including the fact that whenever a function runs, it cannot be pre-empted and will run entirely before any other code runs (and can modify data the function manipulates). This differs from C, for instance, where if a function runs in a thread, it may be stopped at any point by the runtime system to run some other code in another thread."_ https://developer.mozilla.org/en-US/docs/Web/JavaScript/EventLoop#run-to-completion –  Jun 28 '21 at 08:08
  • 1
    As far as I understand the JavaScript Event Loop your approach won't work. –  Jun 28 '21 at 08:09
  • 1
    @pa - as explained i cant have the function be async, htats the same as telling it returns promise itself, but i need to return value right away, and await needs to be within async function.. .soooo..... that is not a good answer – Peminator Jun 28 '21 at 08:10
  • 2
    you can't turn async code into sync in javascript – PA. Jun 28 '21 at 08:11
  • im aware i cant make fetch to sync, that why im trying to run loop to wait while it is resolved instead – Peminator Jun 28 '21 at 08:12
  • 1
    As long as your function is in the loop no other function is executed. You can't wait in a loop for an async function in JavaScript. –  Jun 28 '21 at 08:13
  • any other solution how to get sync function to return response form url request ? Afaik there is possble oin old jQuery do this but since 1.8 even the {async:false} there may be ignored – Peminator Jun 28 '21 at 08:13
  • 1
    Use [XMLHttpRequest](https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest) –  Jun 28 '21 at 08:15
  • 1
    "im aware i cant make fetch to sync" sorry, you can't. There existed indeed a sync XmlHttpRequest, deprecated in current browsers. – PA. Jun 28 '21 at 08:16
  • Does this answer your question? [Call An Asynchronous Javascript Function Synchronously](https://stackoverflow.com/questions/9121902/call-an-asynchronous-javascript-function-synchronously) – MauriceNino Jun 28 '21 at 08:20
  • See [Using XMLHttpRequest](https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/Using_XMLHttpRequest#types_of_requests) for an explanation on how to make a synchronous (blocking) request. – 3limin4t0r Jun 28 '21 at 08:26

1 Answers1

-1

Save yourself a few headaches, drop all the .then() and use the async/await syntax instead. No need for dirty timeout/while hacks.

I renamed syncFetch to asyncFetch, because your original code was never synchronous in the first place (and that's precisely why you are struggling so much, you believe it is when it's not). async/await don't make the code synchronous either. It's just awesome syntactic sugar around Promises.

(EDIT : you said in the comments that you can't add the async keyword to the parent function (asyncFetch), so here's a workaround to place it inside :

function asyncFetch(url) {

    async function a() {
        try {
            const response = fetch(url, {
                headers: { 'Content-Type': 'application/json' },
                method: 'POST',
                timeout: 1500,
                body: JSON.stringify({ cmd: 'init' })
            });
            const data = await response.json();
            return data; // This is a Promise<data>, not data directly, so it needs to be awaited
        } catch (e) {
            console.log('error', e);
            return null
        }
    };
    
    return a();
};

(async () => {
    console.log('RETVAL', await asyncFetch('http://127.0.0.1:3333/')); // Needs to be awaited, and therefore also needs to be inside an async function
})();
Jeremy Thille
  • 26,047
  • 12
  • 43
  • 63
  • bro thanx, but that was the very first attempt, but i can not modify the parent fn calling this at the moment, and there is the issue, you can ony use await in async fn, so for me this is not usable... - as recommended by others, i ended up using XMLHttpRequest, and hope its support will not be dropped any soon :( – Peminator Jun 28 '21 at 11:32
  • Declare another async function inside the parent one and call it? I have updated my answer with how to do that – Jeremy Thille Jun 28 '21 at 11:43