We’ve started refactoring our code for it to be compatible with Meteor 3.0, and part of it is moving the server code from the old sync Mongo API to the new async Mongo API. For example, findOne will now be findOneAsync. To keep the flow of our code working as intended, we must use await when calling these async functions and, therefore, the functions in which they are called must be made async.
This is only required on the server. However, for the sake isomorphism (keeping the code similar everywhere) we also wanted to refactor our client code. However, while doing this, we ran into two problems:
Secondly, we ran into problems for the Template onCreated and onRendered callbacks. Making onCreatedasync makes it so that onRendered can be called before the onCreated finishes running, which can break some of our logic. Some workarounds can be made so onRendered awaits for onCreated, but these don’t seem like a good solution.
We would really like to refactor our client to keep the code similar between client and server, but these issues would make the code more complex than just keeping the code different between them.
Is there something we are missing that could solve these problems, or would we just need to deal with the added complexity in the client code? Also, what are you doing about it in your 3.0 projects? Are you keeping the code similar between server and client despite these issues or did you prefer to keep them different so the client code wouldn’t become much more complex?
@float07 do you rely on strict isomorphism? Because if not, you can safely remain with the sync mongo methods on the client. Saved me a lot of headaches lately
@jkuester no I don’t, but it would be nice to be able to keep the code similar between client and server. Less complexity and less things to think about when coding. It’s not a big deal if we can’t do that. It’s just something we would like to have.
For now it seems that the best approach will be to keep using the sync Mongo API in the client. Anyone have any idea if there are plans to make it easier to deal with async code in these scenarios I mentioned in the client?
I spent some effort converting client code to async for the sake of isomorphism, too, but had to roll a lot of it back. One big reason was that an await operator causes a return to the event loop, which means the ordering of code running changes. That exposed a lot of questionable code that depended on things happening in a certain order, and it wasn’t worth it to rework it to be more robust.
Initially we had the same plans, but have decided to keep ‘pure’ client code as is to indeed avoid the issues you mentioned. With ‘pure’ I mean everything user interface oriented, only those pieces of code where we really want to have code run on server and client side (the optimistic updates) when doing a back end call. Many previously ‘shared’ server calls are being moved to ‘server’ only (effect is that you client code has to wait for the round trip of the data via the subscriptions - but that’s not always that bad).
Async in OnCreated we already encountered e,g. when dealing with video/audio setups, the simple solution there is to let the OnRender wait on an Reactive variable that indicates end of OnCreated (which typically only happens once). If only used in those ‘exceptional cases’ , it’s acceptable.
We have been idle for a while on Meteor 3.0 refactoring but will start on it again shortly. I’d like more people to post their experiences (as we have also been doing and will do again when needed).
Thank you all for sharing, and sorry it took me a while to get back to this post.
After talking with my team, we decided to drop isomorphism for now, and let the client and server code be different regarding async and await. This means we will use the async versions of functions in the server, since they are needed, but we will use the sync versions on client.
We will keep this decision until we are sure the client issues mentioned won’t be a problem for us (when they get fixed or when we find a good workaround).