wait for Promise.all in a synchronous function, basically blocking! javascript

和自甴很熟 提交于 2021-01-07 03:28:03

问题


I have alot of syncrhounous functions that i want to execute before that are basic ajax requests, these request will render html to the DOM.

In order to do this i had to execute all of this synchrounous requests one by one. But i somehow want to these synchrounous functions asynchrounous all at the same time and wait for them to finnish in order to speed things up. This has to happen inside a synchrounous function. But my understanding is that this doesnt work in javascript, but i would like to hear what you guys have to say.

So my attempt was to add all of these synchrounous requests into asynchrounous promises and then do a Promise.all call. I cant wait for the promise.all().then because the main thread will keep on execute the rest of the code after this main synchrounous thread/function. So i wonder if there is a way to block the main thread in order to wait for these asynchrounous calls

heres a short illustration of what im talking about

var syncfunc = () => {
var getPromise = () => {
    return new Promise((resolve) => {
        var asyncAjaxRequest = async function() {
            doSomeStuff();
            resolve();
        }
    })
}
var promises = [getPromse(), getPromse(), getPromse()];


Promise.all(promises);

console.log('i want this console.log to execute after all promises executed doSomeStuff');

/**
 * 
 * Promise.all(promises).then(() => {
        // I cant use this, because its script in other files that will execute if i wait like this
    })
 */
}

I know .then will execute when all resolves are done, but i basiacally want to block this synchrounous thread waiting for all other asynchrounous to finish.

If i could i would ofcourse change the structure into my needs, but the problem and the reason why im trying to do this is because im using sitevision framework, and want to add some content to the dom before a print module opens the print window. To call every function synchrounous is just not the way to go, its to slow. Ive also tried to set window.print = null to make the print function disabled, and then add the print function back when promises resolves, but it simply doesnt work


回答1:


You cannot make an asynchronous operation turn into a synchronous one in plain Javascript (without external code). The event driven JS engine just doesn't work that way.

By definition, an asynchronous operation starts the operation (handing execution off to native code) and then returns back to the interpreter which then continues to execute the code that follows. The native code will add an event to JS event queue when it finishes to allow the interpreter event loop to service the completion of the asynchronous operation. If you were the create some sort of "block" such as a semi-infinite while loop, that would "block" the interpreter from executing more code, you end up in a stalemate. The loop that is blocking the interpreter prevents the JS interpreter from ever getting to the point where it can ever process the event that signals the end of the asynchronous operation. So, you have a loop waiting for something to finish, but the thing it's waiting for can't finish until the loop finishes - stalemate.

So, because of the single threaded event loop nature of the JS interpreter, you can't (purely in Javascript) block waiting for the end of an asynchronous operation.

Pretty much always, the correct design is to refactor the surrounding code/infrastructure to work with an asynchronous operation and asynchronous result (callback or promise).


If this is node.js, there are a couple of horrific hacks that can get you this result, but they block the entire interpreter so are almost never a desired design.

The first option involves writing a custom nodejs plugin (async operations done in native code) that provides a blocking interface that just doesn't return until the operation is done.

The second option involves using the synchronous child_process operations (such as child_process.execFileSync() to create a blocking child process, run your code in that child process and then continue when that process finishes.

Both I could consider pretty bad hacks and pretty much never the desired way to solve such a problem. But, I did want to show you what has to be done in order to block for an asynchronous operation (it has to be moved out of Javascript or out of the process).


If you can't figure out how to solve your real problem with non-blocking, asynchronous operations, I'd suggest you post a new question where you describe in detail exactly what the real problem is and we can help you find an asynchronous design that would work for your situation. If you post a link to the new question in a comment here, some of the people engaged here may check in on the new question and attempt to help.




回答2:


You could use async/await to solve this. This is how you do it:

async function promiseSolver() {
var getPromise = () => {
    return new Promise((resolve) => {
        var asyncAjaxRequest = async function() {
            doSomeStuff();
            resolve();
        }
    })
}
var promises = [getPromse(), getPromse(), getPromse()];


await Promise.all(promises);

console.log('i want this console.log to execute after all promises executed doSomeStuff');

/**
 * 
 * Promise.all(promises).then(() => {
        // I cant use this, because its script in other files that will execute if i wait like this
    })
 */
}

Basically, your code will wait until the .all is completed and then will continue with processing. Take into consideration that while the code execution is synchronous, the code will be non blocking.



来源:https://stackoverflow.com/questions/58842521/wait-for-promise-all-in-a-synchronous-function-basically-blocking-javascript

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!