简体   繁体   中英

Force asynchronous function to be synchronous without async await

I need to force an asynchronous function to run synchronously. My situation is really complicated so I'll try to explain.

I am developing a Ionic application that communicates with a server.

  • In this application, I am charging an html page generated by a webservice, creating a new component with createComponent, and compileModuleAndAllComponentsAsync.

  • In this html sent by webservice, there are some script tags. these scripts are custom javascript made by other persons, but they use functions created by us. As an example, we made a fonction "createdByUs". And other persons can make custom javascript with it (example below).

  • The "createdByUs" function were created before the Ionic application, and many persons have used it. but It has another behavior in ionic, and that behavior is asynchronous, event if the function was synchronous before.

  • Now I have to adapt this function for the ionic application and, since the custom scripts have been created before, I must edit the "createdByUs". The code works well, it's juste that it is asynchronous, so the rest of the custom code executes before the end of "createdByUs"

  <!-- our function -->
  <script type="text/javascript">
    inIonic = true;
    function createdByUs(){
        if(inIonic){
            new Promise(function(resolve, reject) {
              setTimeout(() => {
                console.log('Promise is created and consumed');
                resolve('Promise is created and consumed');
              }, 5000);
            });
        }else{
            console.log("nice synchronous code");
        }   
    }
  </script>

  <!-- custom functions made by other persons I can not modify -->
  <script type="text/javascript" id="customScript">
    createdByUs();
    console.log("other code that must wait for createdByUs");
  </script>

Since I cannot modify the custom script, I cannot simple put "cratedbyus" as async and use await for it everywere. is there a solution for my problem ?

--- EDIT Some precisions about the project : It's a sort of "page editor", we provide a graphic interface, and an area where people can define custom scripts. I am working on an application that would display these pages and were the scripts would work. but some functions don't work in Ionic, so I have to redefine them. To run the ionic code, I call an event in createdByUs that is received in ionic. It works well, excepts the event is asynchronous, and in addition, it adds html elements in an ngfor, and ionic doesn't create the elements immediately when you modify you array source of ngfor, so the generation of html in ngfor is asynchronous too. it's endless...

No. You can't do that. If you could do that, it would create various problems (eg the setTimeout callback could not run to actually resolve the promise, as the thread would be blocked waiting on the promise), therefore it cannot be done in any way, and it won't be possible in the future.


You might say

But why isn't there a way, that behaves similar to await inside of non async functions, so that the running execution context gets stored, removed from the stack, and then later resumes when the promise resolves? .

Well for sure one could do that, but that would break the run to completion guarantee of functions, in other words it would make every piece of code non deterministic, and thats generally a bad thing (in other words: concurrent modifications, out of order execution etc.).

But there is that "global await proposal" that allows to await on the top level, outside of async functions?

Yes, but that is restricted onto the top level, also the execution order is still deterministic (all required modules finish before the module depending on it gets run).

You could create a bit of a hack.

Run the async function as is but return the promise. Then once the promise resolves, then you load the other script.

myPromise.then(() => {
  const script = document.createElement('script')
  script.src = 'path/to/otherScript'
  document.getElementsByTagName('body')[0].appendChild(script)
})

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM