Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there a better way to do this with promises?

Tags:

javascript

I used the code below for years when I want to open a window and check when an specific element becomes present in the DOM of the opened window. It works fine, never had a problem. PS: assume jQuery is already imported into this project.

openedWindow = window.open("http://localhost/teste1.php");

myClock = window.setInterval(

    function() {

        if ($(openedWindow.window.document).find("#myElement").length == 1) {

            window.clearInterval(openedWindow);

            //DO MY STUFF HERE.

        }

    },
    100

);

So yesterday a friend of mine came to me, saw this code and said "You should do that with promises". He said he didnt know how promises worked in depth but he said my code would get smaller and easier to read.

Ok. I dont know promises too. So I studied for over an hour and came up with the code below that works "fine". Except it's a lot bigger and I cant find it easier to read at all.

new Promise(function(resolve,reject) {

    openedWindow = window.open("http://localhost/teste1.php");

    window.setInterval(

        function() {

            window.clearInterval(openedWindow);

            if ($(openedWindow.window.document).find("#myElement").length == 1) {

                resolve(true);

            }

        },
        100

    );

}).then(

    function(result) {

        if (result) {

            //DO MY STUFF HERE.

        }

    }

);

So was my friend wrong? Or I am the wrong one doing the wrong thing with prommises? Is there a better way to do that with promises that I, a newbie in this subject, and not seeing?

like image 699
Samul Avatar asked Mar 05 '23 05:03

Samul


1 Answers

 Disclamer:

I will leave my answer since I believe it is useful in the context of understanding Promises. The question is related to wait for stuff in the DOM, but I believe OP's main concern is to understand why one would use a Promise over a callback.

However, said so, for the specific problem related to react to DOM changes, Nino's answer is the best.

Original answer

Except it's a lot bigger and I cant find it easier to read at all.

Well, the idea I think is that:

  1. You expose a function like waitForElement which takes an element and returns a Promise that resolves when the element is found.
  2. Now any part of your code can use this function to get a Promise of element being found. This is important because you can attach callbacks to already resolved Promises and still get it run (this is important if you're using a Promise that waits for a database connection, for instance).

So your function would be something like:

function waitForElement(element){
 return new Promise(function(resolve) {
    // maybe uri could be a param too
    openedWindow = window.open("http://localhost/teste1.php");

    window.setInterval(

        function() {

            window.clearInterval(openedWindow);

            if ($(openedWindow.window.document).find(element).length == 1) {
                resolve(true);
            }
        },
        100
    );
});
}

Note the return at the beginning of the method. So now any part of your code could call:

waitForElement('#foo').then( // do my stuff //);

This is still pretty much the same, as you say. However, a good thing about promises is that them allow to attach callbacks, and they cache the async operations, so now you can:

const fooIsPresent = waitForElement('#foo');

// later in your code
fooIsPresent( // some stuff //);

// and even later, maybe minutes later:
fooIsPresent(// still more stuff //);

Now, if the element still is not present, the stuff callbacks will be invoked when the moment arrives.

However, if the element was already found, and you call fooIsPresent after that, the callback will be executed immediately (in the next tick).

And if you want some stuff to always happen before another, you can chain them:

fooIsPresent.then(// first stuff //)
.then(// second stuff //);

So yes, the code is bigger and maybe a bit less clear, but now is more useful and you can use it in some handy ways.

like image 171
Sergeon Avatar answered Mar 11 '23 15:03

Sergeon