0

I'm wondering if there is any way to "pause" script execution until a promise is resolved and only than continue execution of that specific script.(i know i can use .then() and in es6 i can even use await , but that's not what i'm asking). i can implement sleep function like that:

function sleep(milliseconds) {
  var start = new Date().getTime();
  for (var i = 0; i < 1e7; i++) {
    if ((new Date().getTime() - start) > milliseconds){
      break;
    }
  }
}

can i check on each second the promise status? or because js is single threaded this will actually freeze everything? any messy way to wait for a promise synchronously ?

Edit: My goal is to handle this situation:

function loadScript(src) {
    try {
        var parent = document.getElementsByTagName('head')[0] || document.documentElement;
        var httpRequest = new XMLHttpRequest();
        httpRequest.open('GET', src, false);
        httpRequest.send();
        var script = document.createElement('script');
        script.type = 'text/javascript';
        script.text = httpRequest.responseText;
        parent.appendChild(script);
    } catch (e) {}
}

this function is located inside a third party js , now i can hook the XMLHttpRequest object and intercept that call and make it async but this will mess up everything , any ideas?

Uwe Keim
  • 39,551
  • 56
  • 175
  • 291
avi dahan
  • 539
  • 3
  • 19
  • 3
    Your *sleep* function actually blocks browser and never end. – Justinas Aug 27 '18 at 08:16
  • @Justinas it does end after some miliseconds... my question is in the time this loop runs the promise status can change? – avi dahan Aug 27 '18 at 08:18
  • 1
    No, your code will execute `1e7` iterations faster than `new Date().getTime() - start` reaches `miliseconds` – Justinas Aug 27 '18 at 08:20
  • @Justinas Ok thanks for the insight , but the question is still the same, if i will loop and check the promise status and actually "hang " execution , the promise status can change? or i will just loop forever? – avi dahan Aug 27 '18 at 08:21
  • Oops, seems like a [XY Problem](http://xyproblem.info/). – NoobTW Aug 27 '18 at 08:47
  • @t.niese the loadScript uses sync xhr which actually freezes everything until it finishes so i thought i can do a little hack and make it async without damaging the code – avi dahan Aug 27 '18 at 08:53
  • If the foreign script relies on `loadScript` being sync then there is no way around it. No matter how you want to fix that you always need to wait until the script is loaded. So you always will _"freez"_ the browser until the script is loaded. – t.niese Aug 27 '18 at 08:53
  • @t.niese yes i know that but if i will control the execution i can "freeze" the browser on my own terms and set my own timeout and such.... – avi dahan Aug 27 '18 at 08:56
  • @avidahan but what did you gain if it freezes anyway, a freez is a freez. You need to halt the execution at the point where `loadScript` is called if the code following the `loadScript` relies on the script beeing loaded and executed sync. So no matter how you try to manage that the script halts at that part, you will always result in that context to freez. It will not change the original situation. (Or you found a browser bug and you don't really want to relay on that). You can only fix that sync loading if the code following `loadScript` does not require that the code is loaded sync. – t.niese Aug 27 '18 at 09:02
  • @avidahan If you can move the library in a separate iframe and this library does noting UI relevant only some calculations, then you can do multiprocessing. Pass the data that should be process to the iframe, process the data in the iframe and then pass the data back to your main window. Your main window will treat this as an async request using a callback or a promise, and your iframe might have some blocking and freezing of in the iframe. – t.niese Aug 27 '18 at 09:06
  • @t.niese you can see that the loadScript func itself is depended on the response from the sync xhr "script.text = httpRequest.responseText;" so there is no way to make this async and maintain functionality . – avi dahan Aug 27 '18 at 09:06
  • @t.niese yes i can actually execute this code in an iframe , my question is if i will execute this code in an iframe and hook the xhr object and retrieve the request async with a promise on the main window and in the meantime the code in the iframe won't continue executing ? – avi dahan Aug 27 '18 at 09:08
  • `hook the xhr object and retrieve the request async with a promise on the main window and in the meantime the code in the iframe won't continue executing` no that's not possible. Why they do `parent.appendChild` and how to actually solve that is not possible to say without seeing reading all of their code. But you maybe need to create an `iframe` in an `iframe` or maybe `window.parent = window` in the `iframe`, might also work. But what ever you do the idea with waiting sync for a Promise wont work. – t.niese Aug 27 '18 at 10:04

5 Answers5

0

You can do sleep like this:

function sleep(duration) {
  return new Promise(function(resolve, reject) {
    setTimeout(()=> { resolve(0) }, duration);
  })
}

And call sleep when you need with await sleep(1000); //miliseconds ;

NoobTW
  • 2,466
  • 2
  • 24
  • 42
  • I know i can do that but i was actually asking something differently , if you will call this function you will get a promise in return and the js will continue executing (i don't have async function to use) and that's not what i need – avi dahan Aug 27 '18 at 08:20
  • You can use async function IIFE with this sleep function. https://stackoverflow.com/questions/40745153/es8-immediately-invoked-async-function-expression – NoobTW Aug 27 '18 at 08:22
  • I don't think there's another way without blocking browser? I'd like to see if there are still other ways. – NoobTW Aug 27 '18 at 08:23
  • i will edit my question to add more details i guess i wasn't specific enough – avi dahan Aug 27 '18 at 08:23
0

You need this?

function sleep(delay) {
  var start = new Date().getTime();
  while (new Date().getTime() < start + delay);
}

sleep(2000)

alert('Hello!')
0

can i check on each second the promise status?

If it has to be sync then no, as long as your sync script is running no other code will be executed.

or because js is single threaded this will actually freeze everything?

If it is all sync then, yes it will freeze everything and the Promise won't resolve because the sync script that is checking the status of the Promise is blocking.

any messy way to wait for a promise synchronously ?

No, there is no sync way to wait for a Promise to resolve.

Promises to don't create multi-threading in the JavaScript context. Promises allow to make cooperative multitasking easier, especially with the introduction of await/async, but the code is still single threaded.

t.niese
  • 39,256
  • 9
  • 74
  • 101
  • Great answer thanks!, i can think on several dirty hacks to achieve this i just need to know if i'm in the right direction, one of my ideas is to execute the script inside an iframe and hijack the xhr call and make it async and call the async xhr in the main window and freeze the iframe window until my promise resolve, can i do that? – avi dahan Aug 27 '18 at 08:32
  • @avidahan Trying to do a such a hack looks like you have a really broken design so to `i just need to know if i'm in the right direction`, has to be answer with **no you are definitely on the wrong direction**. And any solution you will find that will allow some kind of sync multi tasking will most certainly fail with browser updates. So you really should stop to find such a solution and you should fix the other part of your code. – t.niese Aug 27 '18 at 08:45
  • as i mentioned in my edit , that's not my design that code is from third party js and i just want to to eliminate the sync xhr without damaging the code – avi dahan Aug 27 '18 at 08:50
0

Is something like this you are looking for ? Sorry for that I didn't understand your problem perfectly though.

var promise = new Promise((res, rej) => $.getJSON( "https://jsonplaceholder.typicode.com/todos/1", res, rej))

while(promise.status === 'Pending') { // this waits for the promise
  continue;
}

promise.then(console.log)
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
Shanaka Rusith
  • 421
  • 1
  • 4
  • 19
-1

Usually, for a dirty hack you just set an infinite interval to check whatever you need, and when it becomes true, clear that interval and call whatever function to proceed with intended execution.

mohkamfer
  • 435
  • 3
  • 12