Server-side issues implementing Push notifications with exponent-server-sdk-node


#1

Hi! First of all, I’m half-way done with my startup’s first mobile app using Expo and I’m loving it. Thanks for your great work!

Today I’ve been trying to implement push notifications; the app is successfully sending its push token to the server, but then when the server tries to send a message I get an error I don’t understand and I don’t know how to debug.

Client-side, for now, I’m just using the same code in the documentation.

Server-side, I save the tokens and send a message every X seconds:

This saves the tokens, verifying they are well-formed ExpoPushTokens:

// Save the tokens

const tokensSet = new Set([])

const registerToken = token => {
 if (!Expo.isExpoPushToken(token)) {
    console.error(`Push token ${token} is not a valid Expo push token`);
  }
  else if (!tokensSet.has(token)) {
    console.log(`- New token: ${token}`)
    tokensSet.add(token)
  }
}

app.post("/api2/push", (req, res) => {
    if (req.body.token) 
      registerToken(req.body.token)
    
    res.sendStatus(501)
  })

And here is the function that fails. It produces Messages just like I saw in exponent-server-sdk-node’s documentation, creates a chunk and sends it:

// Write a message for all tokens

const writeToAll = async msg => {
  const tokensArray = Array.from(tokensSet)
  
  if (tokensArray.length > 0) {
    const messages = tokensArray.map(token => ({
      to: token,
      sound: 'default',
      body: msg,
      data: { msg },
    }))
    
    console.log(`writing to ${tokensArray.length} users`)
    console.log(messages)
    
    const chunk = expo.chunkPushNotifications()

// try {
      const receipts = await expo.sendPushNotificationsAsync(chunk)
      console.log(receipts)
//}
//    catch (e) {
//      console.error(`- error sending the chunk :( ${e}`)
//    }
  }
  else {
    console.log(`cant write, ${tokensArray.length} users`)
  }

  return tokensArray.length
}

I’m just running this function every 30s:

setInterval(async () => { writeToAll(`Hey !!`) }, 30*1000)

Finally, I’m getting this cryptic error:

(node:79055) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 15): TypeError: Cannot read property 'Symbol(Symbol.iterator)' of undefined

The log shows apparently-sane info:

- New token: ExponentPushToken[REDACTED]
::1 - - [15/Feb/2018:16:15:50 +0000] UNKNOWN "POST /api2/push HTTP/1.1" 200 2
...
writing to 1 users
true
[ { to: 'ExponentPushToken[REDACTED]',
    sound: 'default',
    body: 'Hey !!',
    data: { msg: 'Hey !!' } } ]

I have no idea what to do, and I don’t dare to create an issue in Github since probably it’s my fault. Is there anything I’m misunderstanding here?

By the way, my app uses:

"expo": "^25.0.0",
"react": "16.2.0",
"react-native": "0.52.0",

The server uses expo-server-sdk version 2.3.3, and node 8.7.

Am I doing anything wrong? Can anyone make sense of this error? I’ve been reading expo-server-sdk’s code and nothing has popped to my eye…

Thanks a lot!


#2

Hi @jkurei! I think all that’s wrong is you need to pass in messages to expo.chunkPushNotifications() like expo.chunkPushNotifications(messages). Can you try that and let us know if it works?

Thanks for providing all of the code :slight_smile:


#3

You are right of course :sweat_smile: what a silly mistake. Thanks a lot for your help!

I rewrote that part several times trying to fix a previous issue, and introduced that mistake. Too much time looking at the same code and you develop a weird kind of blindness.

Now I’m back at hunting the previous error:

error sending the chunk :( Error: "value" must be an object, "value" at position 0 fails because ["0" must be an object]

Here is the content of the messages variable:

[ { to: 'ExponentPushToken[y-MfqeM6ufH6d5EAeql0aS]',
    sound: 'default',
    body: 'Hey !!',
    data: { msg: 'Hey !!' } } ]

I hope it will be another dumb mistake…


#4

I got it working by not using the chunks, but passing messages straight to sendPushNotificationsAsync. Now I see I was doing that wrong too: sendPushNotificationsAsync expects chunks[0], and expo.chunkPushNotifications returns an array of chunks.

chunkPushNotifications(messages: ExpoPushMessage[]): ExpoPushMessage[][] {
  ...
}

async sendPushNotificationsAsync(messages: ExpoPushMessage[]): Promise<ExpoPushReceipt[]> {
  ...
}

The lesson is to stop rushing things, be more careful, and rest your eyes and mind from time to time :slight_smile:

Thanks again for your help @jesse.


#5

Glad you got it working!


closed #6

This topic was automatically closed 15 days after the last reply. New replies are no longer allowed.