1
votes

I have something like this:

const promises = [];

    l = niz.length;
    for (i = 0; i < l; i++) {
      if(niz[i].length === 0) {
          continue;
      }

      promises.push(admin.messaging().sendToDevice(niz[i], payload, options));
    }

   return Promise.all(promises).then((response) => {
        return cleanupTokens(response, tokens);
        //return resolve(); 
    }).then(() => {
        return resolve();
    });

but always I have crash in firebase logs:

TypeError: Cannot read property 'forEach' of undefined at cleanupTokens (/user_code/index.js:193:20) at Promise.all.then (/user_code/index.js:169:20) at process._tickDomainCallback (internal/process/next_tick.js:135:7)

Response is:

response: [ { results: [ [Object] ], canonicalRegistrationTokenCount: 0, failureCount: 0, successCount: 1, multicastId: 5591935326806715000 } ]

response: undefined

cleanup is:

function cleanupTokens(response, tokens) {

// For each notification we check if there was an error.
const tokensToRemove = {};

console.log('response: ', response);

console.log('response: ', JSON.stringify(response.results));

response.results.forEach((result, index) => {
       const error = result.error;

       if (error) {
         console.error('Failure sending notification to', tokens[index], error);

         // Cleanup the tokens who are not registered anymore.
         if (error.code === 'messaging/invalid-registration-token' ||
             error.code === 'messaging/registration-token-not-registered' ||
             error.code === 'messaging/invalid-recipient') {

           tokensToRemove[`/tokens/${tokens[index]}/g`] = null;
           tokensToRemove[`/tokens/${tokens[index]}/l/0`] = null;
           tokensToRemove[`/tokens/${tokens[index]}/l/1`] = null;
         }
       }
   });

   return admin.database().ref().update(tokensToRemove);
}

Any help with cleanup tokens?

1
It looks like response.results is not an array. Can you replace console.log('response: ', response.results); with console.log('response: ', JSON.stringify(response.results)); and add that log to your question.Frank van Puffelen
off course, it's undefinedkacerac
Interesting, since your original log showed results: [ [Object] which seems to indicate that results is an array. But if it is undefined you should check for that before calling forEach on it. So if (response.results) { response.results.forEach(...Frank van Puffelen

1 Answers

0
votes

You chose to send each notification separately to each user, making the response become "wrapped" as a singleton of response, and each response is also a singleton of itself - making it weird to access (response[0].results.foreach should probably work)

But even then, you'd have only 1 item to go trough, because you made each notification to be sent individually. I believe it is much more efficient to have a 1 time sendToDevice() request to all of the relevant tokens, instead of sending them separately.

Consider changing your first code to this:

//const promises = [];
var tokens = [];

l = niz.length;
for (i = 0; i < l; i++) {
  //if(niz[i].length === 0) {
  if(niz[i].length > 0) //I guess those are your relevant tokens
      tokens.push(niz[i]); //Fill in the relevant tokens
}

//promises.push(admin.messaging().sendToDevice(niz[i], payload, options));

return admin.messaging().sendToDevice(tokens, payload, options)
.then(response => {
    return cleanupTokens(response, tokens);
})
.then(() => {
    return resolve();
});

//return Promise.all(promises).then((response) => {
//    return cleanupTokens(response, tokens);
//    //return resolve(); 
//}).then(() => {
//    return resolve();
//});

The rest of your code should work after this change.

(Few credits to @Frank for his comment - the JSON log helped determining the issue)

EDIT:

Regarding your comment, if each niz[i] item is an array itself, you could do this:

const promises = [];

l = niz.length;
for (i = 0; i < l; i++) {
  if(niz[i].length === 0) {
      continue;

  //promises.push(admin.messaging().sendToDevice(niz[i], payload, options));

  var newPromise = return admin.messaging().sendToDevice(niz[i], payload, options)
  .then(response => {
    return cleanupTokens(response, tokens);
  })
  .then(() => {
      return resolve();
  });

  promises.push(newPromise);

}

return Promise.all(promises);

//return Promise.all(promises).then((response) => {
//    return cleanupTokens(response, tokens);
//    //return resolve(); 
//}).then(() => {
//    return resolve();
//});