Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
557 views
in Technique[技术] by (71.8m points)

javascript - Make a jquery function wait till it's previous call has been resolved

So, I've searched for this high and low and maybe I'm just having trouble understanding jQuery's deferred function or I'm completely on the wrong track. So any help would be appreciated folks!

I basically have a custom jQuery function messager that displays a message with a fadeOut and fadeIn.

(function ( $ ) {

    $.fn.messager = function(message, effect, speed) {

        $(this).fadeOut(speed).delay(speed).text(message).fadeIn(speed);

        return this;
    };

}( jQuery ));

So, I have a div called $elem and when $elem.messager gets called multiple times (with different messages), I would like the messager function to wait till its last call has finished. As in the last FadeIn has finished. Because currently what's happening is that the second call of the function is overwriting the animation effect of the first call of the function.

Any ideas?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

jQuery Deferred Way

jQuery Deferred object (roughly compromising CommonJS Promises API) can help us managing queued operations. Here is my implementation of queuing messages. You can pass through multiple messages as an array in one call, or synchronize different message boards easily because #messager() returns jQuery object itself but also wrapped as a promise object which will be resolved just when message(s) being displayed.

(function ($) {
    function awaits($el) {
       var awaits = $el.data('_awaits');
       awaits || $el.data('_awaits', awaits = []);
       return awaits;
    }
  
    function resolveNext(curr /*, ignored */) {
       var head = awaits(this).shift();
       if (head === curr) {
           resolveNext.call(this, 'not await');
       } else {
           head && head.resolve();
       }
    }
  
    function display(message, speed) {
        var $self = this, await = $.Deferred(), willDone = $.Deferred();
        awaits($self).push(await) > 1 || await.resolve();
        
        await.done(function() {
            function reveal() {
               $self.text(message).fadeIn(speed, function() {
                   resolveNext.call($self, await);
                   willDone.resolve();
               });
            }

            $self.fadeOut(speed/2, reveal);
        });
        return willDone.promise(this);
    };

    $.fn.messager = function(message, speed) {
        speed = speed || 500;

        if ($.isArray(message)) {
            var arr = [];
            message.forEach(function(m) {
                arr.push(display.call(this, m, speed));
            }, this);
            return $.when.apply(this, arr);
        } else {
            return display.call(this, message, speed);
        }
    }

}( jQuery ));



function play() {
  $('#msgbox1').messager(['A demo of', 'queued messages'], 1000);
  for (var i = 3; i > 0; i--) $('#msgbox1').messager(i);
  $('#msgbox1').messager(['Ready to sing...', 'Singing...']);    
  
  for (var i = 8; i > 0; i--) $('#msgbox2').messager('***');    
  for (i = 1; i < 8; i++) $('#msgbox2').messager(String.fromCharCode(64 + i));
  
  $('#msgbox2')
      .messager('')
      .done(function() { 
          $('#msgbox1')
              .messager(['End of demo.', 'Thank you.', 'Run again?'], 1000)
              .done(function() {
                  $('#msgbox1, #msgbox2').one('click', play); 
                  $('#msgbox2').messager('>');
              });
      });
}

play();
html {
  background: rgba(0, 0, 0, 0.25);
}
#msgbox1, #msgbox2 {
  color: #FFF;
  padding: 0.3em 0.5em;
  font-size: 36pt;
  text-align: center;
  height: 1.8em;
  cursor: default;
}
#msgbox2 {
  color: yellow;
}
<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <title>Queuing Messages with jQuery Deferred Object</title>
  <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
</head>
<body>
  <div id="msgbox1"></div>
  <div id="msgbox2"></div>
</body>
</html>

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...