3
\$\begingroup\$

I'm making a helper function to make setTimeout synchronous. Currently, it is asynchronous so other code runs before the timeout is done.

function syncSetTimeout(func, ms, callback) {
    (function sync(done) {
            if (!done) {
            setTimeout(function() {
                eval("(" + func + ")();");
                sync(true);
            }, ms);
            return;
        }
        eval("(" + callback + ")();");
    })();
}
  • func is a function that should be run after the specified timeout.
  • ms specifies how many milliseconds to wait before running func.
  • callback is the function that runs after the func is done running.

Is there a way to get rid of those eval statements? I've read that eval is evil. I'm also wondering if I can do this without a nested function. If there are any other ways to improve this code then please say so.

\$\endgroup\$
5
\$\begingroup\$

The Eval

Eval is indeed, the monster. There are plenty of reasons why you should not use it, although there are some situations where you are forced to use it. For sure, this is not the requirement in yours situation. If func is a function, you can call it using .apply.

function syncSetTimeout(func, ms, callback) {
    (function sync(done) {
        if (!done) {
            setTimeout(function() {
                func.apply(func);
                sync(true);
            }, ms);
            return;
        }
        callback.apply(callback);
    })();
}

Reference: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/apply

Or event without apply:

function syncSetTimeout(func, ms, callback) {
    (function sync(done) {
        if (!done) {
            setTimeout(function() {
                func();
                sync(true);
            }, ms);
            return;
        }
        callback();
    })();
}

The synchronous

You need to know, that trying to make setTimeout() sync means that you have some very bad design idea behind. You should not do it and you will not be able to make it really sync without killing performance of the browser and UX of your app.

I believe that you would like to create sync delay in your application. You are not the first who wants to do it (most of beginners or people with background from different language). You can take a look at answers to this question from stackoverflow: https://stackoverflow.com/questions/6921895/synchronous-delay-in-code-execution

From the answer to linked question (by OverZealous):

JavaScript is a single-threaded language. You cannot combine setTimeout and synchronous processing. What will happen is, the timer will lapse, but then the JS engine will wait to process the results until the current script completes.

One reason people are trying to take advantage of sync delays is returning result from async code. This is not good strategy in JS. If you would like to return async results just use callbacks or more likely - Promises or Observables.

\$\endgroup\$
  • \$\begingroup\$ I don't really understand what .apply() does. Can you explain? I've tried this page, but that's not very clear. \$\endgroup\$ – ericw31415 Nov 14 '16 at 23:08
  • \$\begingroup\$ Check my updated answer. \$\endgroup\$ – rzelek Nov 14 '16 at 23:14
  • \$\begingroup\$ So are you saying that my function is flawed? \$\endgroup\$ – ericw31415 Nov 15 '16 at 2:05
-1
\$\begingroup\$

There's a simpler solution if you are using nodejs

await new Promise(done => setTimeout(() => done(), 180000));
\$\endgroup\$
  • \$\begingroup\$ Welcome to Code Review! You have presented an alternative solution, but haven't reviewed the code. Please edit to show what aspects of the question code prompted you to write this version, and in what ways it's an improvement over the original. It may be worth (re-)reading How to Answer. \$\endgroup\$ – Toby Speight Apr 8 at 8:04

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.