Sharing state with callbacks?

I have a class that looks like this:

```
class BgDataService extends System.ServiceDelegate {
hidden var sessionId;

// override
(:background_method)
function onTemporalEvent() {
if (sessionId == null) {
Communications.makeWebRequest(..., method(:loginResponseCallback))
}
...
}

(:background_method)
function loginResponseCallback(responseCode as Lang.Number, data as Lang.String) as Void {
sessionId = ...
}
}
```

The problem the value set to `sessionId` in the callback is not visible in `onTemporalEvent` when it's called the next time.

Is this expected? How do I share this state (sessionId) with the callback?

Top Replies

All Replies

  • Add a System.println at the constructor of BgDataService, you'll see that every 5 minutes a new instance is created. You could probably save it in the storage

  • haven't needed to do this, but I think you can use the context parameter for this purpose, see docs: 

    I don't think so, because:

    1) OP wants sessionId to persist over multiple runs of the background process, so the context parameter won't help here. (You can see from the code that sessionId is already a class member variable which is accessible to both onTemporalEvent() and loginResponseCallback().)

    2) it's a very long standing bug (6+ years and counting) that the context arg won't be passed if makeWebRequest fails in certain ways (e.g. BLE and Wi-Fi are disabled), which means a callback that accepts the context parameter will crash with a "Not Enough Arguments" error in those cases.

    https://forums.garmin.com/developer/connect-iq/f/discussion/6866/context-not-passed-in-when-makewebrequest-encounters-system-level-errors

    Of course there is a way around 2), but due to 1), it doesn't matter.

    On a side note, I find it very frustrating that "everyone" (who's been on the forums for a few years) knows about problems like this (where certain things just don't work), but it's never reflected in the documentation. In this specific case, there's a form of the makeWebRequest callback that hasn't worked properly for at least 6 years, but you wouldn't know from looking at the docs. And the worst part in this case is that using the callback with context won't fail every time, just some of the time, which means that you might incorporate it in your code and have no idea there's a problem. (Ofc that's what testing is for.)

  • Of course there is a way around 2)

    it's problematic if the context parameter is not always passed. Without optional parameters or method overloading (which connect iq both doesn't have if I'm not mistaken) I don't see a way around this....

  • Of course there is a way around 2)

    it's problematic if the context parameter is not always passed. Without optional parameters or method overloading (which connect iq both doesn't have if I'm not mistaken) I don't see a way around this....

    The workaround for 2) is in the very thread I linked, and it's not too different from what the OP already has (except that it's a generic, reusable solution). Instead of relying on the API to handle context, you do it yourself.

    You simply define a delegate class for makeWebRequest which has its own context member variable, and a wrapper request function to call instead of calling makeWebRequest directly. When you call the wrapper request function with a context arg and callback arg, the delegate does not pass the context directly to makeWebRequest, but stores the context in its own member variable. The delegate also does not pass the user-specified (*) callback function directly to makeWebRequest, but wraps it in its own wrapper callback function which invokes the user-specified callback with its own context member variable.

    (* here by user I mean dev)