skip to Main Content

I’m quite bad with JS promises and async and I face a problem about it.

First things first the simplified code:

self.addEventListener('push', (event) => {
    const data = event.data ? event.data.json() : {}
    if (isClientFocused()) {
        console.log('Don't need to show a notification.');
        return;
    }
    event.waitUntil(
        self.registration.showNotification(data.title, data)
    )
});

function isClientFocused() {
    return self.clients.matchAll({
        type: 'window',
        includeUncontrolled: true
    })
        .then((windowClients) => {
            let clientIsFocused = false;
            for (let i = 0; i < windowClients.length; i++) {
                const windowClient = windowClients[i];
                if (windowClient.focused) {
                    clientIsFocused = true;
                    break;
                }
            }
            return clientIsFocused;
        });
}

The concept is quite straight forward: my function isClientFocused return true or false depending on the situation and I want to use this value as a condition in my if in my event listener.

I precise that isClientFocused function works well and everytime return the result as expected, but when used in the if condition, it always log Don't neet to show notification.

I guess it’s just an implementation problem but I’m a bit lost right now.

Thanks in advance for your help.

2

Answers


  1. Just add async/await because isClientFocused() returns a promise and it’s truthy and condition is always true. With the resolved value with await you get a proper logic.
    Also you should call event.waitUntil immediately (sync):

    self.addEventListener('push', event => event.waitUntil(new Promise(async (resolve, reject) => {
        try {
            if (await isClientFocused()) {
                console.log('Don't need to show a notification.');
                return;
            }
            const data = event.data?.json() ?? {};
            return self.registration.showNotification(data.title, data)
        } catch (e){
            reject(e);
        }
    })));
    

    I suggest to refactor isClientFocused() with async/await and use async/await as much as possible to avoid then(). Also you could use Array::some() instead of your loop.

    In my experience async/await leads to less bugs and more readable and maintainable when async/await is learned.

    It’s just amazing when I refactor a buggy then() code to async/await the bugs disappeared automatically.

    async function isClientFocused() {
        const windowClients = await self.clients.matchAll({
            type: 'window',
            includeUncontrolled: true
        });
        return windowClients.some(windowClient => windowClient.focused);
    }
    
    Login or Signup to reply.
  2. Cause of this, isClientFocused function is a Promise, when you call it, you have to wait for complete this function.

    The code should look like this;

    self.addEventListener('push', (event) => {
        const data = event.data ? event.data.json() : {}
        isClientFocused().then(res=>{
          if (res) {
              console.log('Don't need to show a notification.');
              return;
          }
          event.waitUntil(self.registration.showNotification(data.title, data))
        })
    });

    Note : Promise gives an output similar to this if you do not wait for a function to run ;

    {"_h": 0, "_i": 3, "_j": {"_h": 0, "_i": 1, "_j": 3, "_k": null}, "_k": null} 
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search