排队通知的模式?

时间:2015-01-09 14:05:48

标签: javascript angularjs

我创建了一个库来弹出一些Toast通知,我试图限制屏幕上的最大通知。

我设法将这个想法提炼成了一个关注者(不要介意代码,只是为了解决问题)。

我有一个创建这些祝酒词的功能:

function createToast() {
  var body = $document.find('body').eq(0);

  var toast = {};
  toast.id = index++;
  toast.el = angular.element('<div class="toast">Toast ' + toast.id + '</div>');
  toast.el = $compile(toast.el)($scope);

  if (maxOpened && toasts.length >= maxOpened) {
    remove(toasts[0].id);
  }

  toasts.push(toast);
  $animate.enter(toast.el, body).then(function() {
    $timeout(function() {
        remove(toast.id);
      }, 3000);
  });
}

基本上它会创建一个带有el的新对象,然后在身体上设置动画。请注意,如果达到maxOpened,则删除第一个。

function remove(id) {
  var toast = findToast(id);

  if (toast) {
    $animate.leave(toast.el).then(function() {
      var index = toasts.indexOf(toast);
      toasts.splice(index, 1);
    });
  }

  function findToast(toastId) {
    for (var i = 0; i < toasts.length; i++) {
      if (toasts[i].id === id) {
        return toasts[i];
      }
    }
  }
}

找到吐司,为假设定动画,然后将其删除。

如果我对它们进行$间隔,请说600ms它有效。

在此尝试:http://plnkr.co/edit/lDnT57FPadCt5Ir5wHuK?p=preview

如果你把它降低到像100ms这样的东西就会开始破坏,不仅会忽略最大值,还会留下一些不会被删除的孤儿祝酒。

所以我不确定这里有什么好方法。我最好的猜测是提供一个队列,所以一旦吐司被删除就开始消耗它,但到目前为止,我还没有成功。

1 个答案:

答案 0 :(得分:1)

最简单的解决方案是将延迟添加到每个吐司中,并且只有在没有或不再达到限制时才开始为吐司设置动画。

首先添加延迟并立即解决,如果尚未达到限制或可以忽略限制:

toast.slotOpen = $q.defer();

toasts.push(toast);
if (maxOpened && toasts.length <= maxOpened || !maxOpened) { // i guess 0 or a falsy value means to ignore the limit
  toast.slotOpen.resolve();
}

您只在插槽打开时启动动画:

toast.slotOpen.promise.then(function() {
  $animate.enter(toast.el, body).then(function() {

最后一件事是解决在旧的toast被删除后新插槽被打开时的延迟:

$animate.leave(toast.el).then(function() {
   var index = toasts.indexOf(toast);
   toasts.splice(index, 1);
   if (maxOpened && toasts.length >= maxOpened) {
    toasts[maxOpened - 1].slotOpen.resolve();
   }  

我调整了您的代码并创建了一个新的Plunker