结合两个承诺

时间:2015-07-29 12:33:48

标签: javascript push-notification promise service-worker

我对JavaScript和承诺都很陌生,说实话,我并不完全理解承诺是如何运作的,所以我需要一些帮助。

我正在使用Google Cloud Messaging将通知从我的网站推送给我的用户。当用户收到通知并单击它时,它会打开存储在IndexedDB中的URL。

MissingMethodException: UnityScript.Lang.Array.IndexOf
Boo.Lang.Runtime.DynamicDispatching.MethodDispatcherFactory.ProduceExtensionDispatcher ()
Boo.Lang.Runtime.DynamicDispatching.MethodDispatcherFactory.Create ()
Boo.Lang.Runtime.RuntimeServices.DoCreateMethodDispatcher(System.Object target, System.Type targetType, System.String name, System.Object[] args)
Boo.Lang.Runtime.RuntimeServices.CreateMethodDispatcher (System.Object target, System.String name, System.Object[] args) 

所以在上面的代码中,我知道getIdb()... then()是一个promise,但event.waitUntil也是一个承诺吗?

上述代码的问题在于,每次点击通知时都会打开Chrome的一个实例,我希望它会利用现有的实例(如果可用)。以下是:

importScripts('IndexDBWrapper.js');
var KEY_VALUE_STORE_NAME = 'key-value-store', idb;

function getIdb() {
  if (!idb) {
    idb = new IndexDBWrapper(KEY_VALUE_STORE_NAME, 1, function (db) {
      db.createObjectStore(KEY_VALUE_STORE_NAME);
    });
  }
  return idb;
}

self.addEventListener('notificationclick', function (event) {
  console.log('On notification click: ', event);
  event.notification.close();
  event.waitUntil(getIdb().get(KEY_VALUE_STORE_NAME, event.notification.tag).then(function (url) {
    var redirectUrl = '/';
    if (url) redirectUrl = url;
      return clients.openWindow(redirectUrl);
  }));
});

但是,现在我有两个promise,getIdb和clients.matchAll,我真的不知道如何组合两个promises和两组代码。任何帮助将不胜感激。谢谢!

供参考,这里是IndexDBWrapper.js:

self.addEventListener('notificationclick', function(event) {  
  console.log('On notification click: ', event.notification.tag);  
  event.notification.close();
  event.waitUntil(
    clients.matchAll({  
      type: "window"  
    })
    .then(function(clientList) {  
      for (var i = 0; i < clientList.length; i++) {  
        var client = clientList[i];  
        if (client.url == '/' && 'focus' in client)  
          return client.focus();  
      }  
      if (clients.openWindow) {
        return clients.openWindow('/');  
      }
    })
  );
});

2 个答案:

答案 0 :(得分:8)

event.waitUntil()接受承诺 - 这允许浏览器让您的工作人员保持活力,直到您完成了您想要做的事情(即直到您对event.waitUntil()的承诺得到解决)

正如另一个答案所示,您可以在Promise.all()中使用event.waitUntilPromise.all()获取一系列承诺并返回一个承诺,因此您可以在其上调用then。当您提供给Promise.all的所有承诺都已解决时,您的处理功能将获得一系列承诺结果。您的代码看起来会像这样(我还没有对此进行过测试,但它应该接近):

self.addEventListener('notificationclick', function (event) {
  event.notification.close();
  event.waitUntil(Promise.all([
      getIdb().get(KEY_VALUE_STORE_NAME, event.notification.tag),
      clients.matchAll({ type: "window" })
    ]).then(function (resultArray) {
    var url = resultArray[0] || "/";
    var clientList = resultArray[1];
    for (var i = 0; i < clientList.length; i++) {
      var client = clientList[i];
      if (client.url == '/' && 'focus' in client)
        return client.focus();
    }
    if (clients.openWindow) {
      return clients.openWindow(url);
    }
  }));
});

答案 1 :(得分:5)

处理多项承诺的一种方法是使用Promise.all

Promise.all([promise0, promise1, promise2]).then(function(valArray) {
    // valArray[0] is result of promise0
    // valArray[1] is result of promise1
    // valArray[2] is result of promise2
});

阅读promise.all - https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/all