1

I can't make JQuery to wait a second before a function is executed. The JQuery script shows notification when user opens a web page. For now, all notifications show immediately but I want them to be added one by one after for example 1000 ms.

I've tried setInterval and setTimeOut but nothing worked.

My code - the notifications are still showing at the same time.

function showLobiboxNotification(msg, onClickUrl) {
    Lobibox.notify('info', {
        title: 'Notification',
        delay: false,
        msg: msg,
        sound: false,
        position: 'left bottom',
        showClass: 'fadeInDown',
        hideClass: 'fadeUpDown',
        rounded: 'true',
        onClickUrl: onClickUrl
    });
    setTimeout('showLobiboxNotification', 1000)
}

$(document).ready(function () {
    $.ajax({
        type: 'GET',
        url: "/ajax/get-base-notifications/",
        success: function (data) {
            $.each(data, function (k, message) {
                setTimeout(showLobiboxNotification(message['msg'], message['url']),1000);
            });
        }
    });
});

Do you have any idea?

Milano
  • 18,048
  • 37
  • 153
  • 353
  • 1
    This smells of an [XY question](http://meta.stackexchange.com/questions/66377/what-is-the-xy-problem). Why do you want to pause? Your (trying) to create timeouts within timeouts, this is going to run very odd. – Liam Aug 12 '16 at 14:06
  • Have you tried triggering custom events and catching them? (See trigger method) Remember that setTimeout doesn't mean to "wait", it just adds the function call a second later to the event loop. – Guillermo Aug 12 '16 at 14:07
  • 1
    Possible duplicate: http://stackoverflow.com/questions/18965768/set-a-delay-in-a-repeating-jquery-ajax-function – IronAces Aug 12 '16 at 14:09
  • The AJAX returns something like this: {'message1':{'msg':'This is a message','url':'Some url'}, 'message2':{'msg'..... For each message1,message2... I call function above which creates a notification. What I want is to set some delay between notifications. – Milano Aug 12 '16 at 14:12
  • Or you can simply use: `showAfterPrevious: true` – Hackerman Aug 12 '16 at 14:19
  • Always read the docs...check this example "Show notification after previous is closed" : http://lobianijs.com/site/lobibox#lobibox-notification-examples – Hackerman Aug 12 '16 at 14:22
  • @Hackerman Unfortunately this isn't my problem because I want to keep them visible, just want to show them one by one after second. – Milano Aug 12 '16 at 14:23
  • @MilanoSlesarik in that case your showLobiboxNotification function could emit a custom event when it finishes. The next notification timeout would not be set until that event triggers. At the moment, if you've got 10 notifications, you'll get all of them 1 second later, because all the timeouts are set at (pretty much) the same instant in time, and all return 1 second later than that instant. – ADyson Aug 12 '16 at 14:27

3 Answers3

2

You need to pass a function to setTimeout. You're calling the function immediately and passing the result.

    $.each(data, function (k, message) {
        setTimeout(function() {
            showLobiboxNotification(message['msg'], message['url'])
        },1000);
    });

Also, this line makes no sense.

setTimeout('showLobiboxNotification', 1000);

If the argument to setTimeout is a string, it needs to be a valid Javascript statement. Just giving the name of a function doesn't do anything.

Barmar
  • 741,623
  • 53
  • 500
  • 612
  • `setTimeout(function() { showLobiboxNotification(message['msg'], message['url']) },1000);` this is wrapping a function within a function - not really necessary. `setTimeout(showLobiboxNotification(message['msg'], message['url']),1000);` will do just as well. – ADyson Aug 12 '16 at 14:19
  • No it won't, that's the whole problem. That calls `showLobiboxNotification` **before** calling `setTimeout`. – Barmar Aug 12 '16 at 14:20
  • no, it absolutely does not. Have you even tried it? Simple example: `var myVar; function myFunction() { myVar = setTimeout(alertFunc, 3000); } function alertFunc() { alert("Hello!"); } myFunction(); ` The alert box will show after 3 seconds. It clearly sets a timeout whereby alertFunc() is executed after 3 seconds. It's just a named function instead of an anonymous one, that's the only difference. – ADyson Aug 12 '16 at 14:29
  • That's different, you didn't write `alertFunc()`, so it passes a reference to the function instead of calling it. – Barmar Aug 12 '16 at 14:30
  • Try `setTimeout(alertFunc(), 3000)` to see something analogous to what he wrote. – Barmar Aug 12 '16 at 14:31
  • Nonetheless, I think the issue is that he wants them to wait one second between notifications, not one second after the ajax returns. This will still just set them all to run 1 second after the ajax returns I think. – ADyson Aug 12 '16 at 14:37
2

You call the method showLobiboxNotification in same time for every notifications.

I think you can do somothing like this

    function showLobiboxNotification(msg, onClickUrl) {
    Lobibox.notify('info', {
        title: 'Notification',
        delay: false,
        msg: msg,
        sound: false,
        position: 'left bottom',
        showClass: 'fadeInDown',
        hideClass: 'fadeUpDown',
        rounded: 'true',
        onClickUrl: onClickUrl
    });
}

$(document).ready(function () {
    $.ajax({
        type: 'GET',
        url: "/ajax/get-base-notifications/",
        success: function (data) {
            var responseIndex = 1;
            $.each(data, function (k, message) {
                setTimeout(showLobiboxNotification(message['msg'], message['url']), responseIndex * 1000);
                responseIndex++;
            });
        }
    });
});
anthony
  • 126
  • 1
  • 4
1

I can see you come from a synchronous language, timeouts are async in javascript, hence you cant append a timeout or a sleep to the end of a function and expect the execution to freeze, because javascript doesnt do that.

wrap the whole showLobiboxNotification function with a timeout. this way its more modular than wrapping the calling of the function with a timeout. and a little bit less complex.

function showLobiboxNotification(msg, onClickUrl, delay) {
    setTimeout(function() {

      Lobibox.notify('info', {
        title: 'Notification',
        delay: false,
        msg: msg,
        sound: false,
        position: 'left bottom',
        showClass: 'fadeInDown',
        hideClass: 'fadeUpDown',
        rounded: 'true',
        onClickUrl: onClickUrl
      });
    }, 1000*delay)
}

$(document).ready(function () {
    $.ajax({
        type: 'GET',
        url: "/ajax/get-base-notifications/",
        success: function (data) {
            $.each(data, function (k, message) {
                showLobiboxNotification(message['msg'], message['url'], k);
            });
        }
    });
});

additionally if you are a fan of functional programming you can write a helper

callAfterDelay(delay, fn, params,) {
    setTimeout(function() {
       fn(...params)
    }, 1000*delay)
}

$(document).ready(function () {
    $.ajax({
        type: 'GET',
        url: "/ajax/get-base-notifications/",
        success: function (data) {
            $.each(data, function (k, message) {
                callAfterDelay(k, showLobiboxNotification, [message['msg'], message['url']];
            });
        }
    });
});
Bamieh
  • 10,358
  • 4
  • 31
  • 52
  • if there were 10 notifications, this will just set 10 timeouts for 1 second's time, but set those timeouts all at once, so effectively they'll still all occur together (or near enough). Certainly not spaced 1 second apart. – ADyson Aug 12 '16 at 14:26
  • simply added a delay, the problem with OP is that he is facing trouble with async and sync, not with code writing. as i said at the beginning of the answer, its async while he thinks its sync. anyways – Bamieh Aug 12 '16 at 14:29
  • 2
    he already had a delay, you just moved where the delay code is written. The issue is that he wants them to wait one second _between_ notifications, not one second after the ajax returns. – ADyson Aug 12 '16 at 14:31
  • ok just spotted the 1000*delay - sorry, not reading properly this afternoon! Ok it might just work then. – ADyson Aug 12 '16 at 14:39