Caching best practice for mobile hybrid/bridge app development - mobile-application

I really need to limit any unnecessary network traffic and server trips. Solution: common sense caching. (I am not going to cache everything under the sun).
However, after reading through the Caching Files documentation and implementing a couple of quick examples, when is the best time to cache an ajax json result? Sure I can do the usual cache/no cache check each time my view is displayed. But is there a way to perform an asynchronous load during initial application startup to prefetch remote data that I know the user is going to need? Is using the connectionStateChanged event the only way (or closest way)? Is there a way to "hook" into the splash screen (yes, I know Apple wants the splash screen for mostly transition)? window.onload?

So if I understand you correctly, you're looking for a way to asynchronously fetch remote resources once for each time the app starts up, and cache those data away?
Our request module is asynchronous by nature, so you could simply drop in a forge.request.ajax to start fetching an Ajax response, then store it away in the preferences module.
Although it's probably identical in practice, you could even wrap it in a setTimeout to make it even more asynchronous:
setTimeout(function ()
forge.request.ajax({
url: 'http://example.com/method.json',
success: function (data) {
forge.prefs.set("method.json-cache", data);
}
});
}, 10);

Related

How to return Vuex-generated page to client on initial Vue load?

I have a Vue / Nuxtjs app which displays lots of user-provided content (think of it as a crowdsourced blog). The content on the client is retrieved and stored in Vuex. When a page is loaded, it displays the current content and then uses fetch to get the updated data. Here is a typical component:
fetch() {
this.$store.dispatch('feeds/refreshLatest')
},
computed: {
feed() {
return this.$store.state.feeds.latest
}
}
where feeds/refreshLatest uses axios to retrieve the posts.
This works quite well. The problem is the initial load is very slow, especially on the front page which has to process and display dozens of articles.
I have SSR enabled, and would like the server to store the content, and then on initial load provide a rendered page to the client. However, the Vuex object on the server seems to be new for each request, and so the client has to wait for the entire set of articles to be fetched before anything is displayed, which is unacceptable. Doing all the fetches only on the client solves this problem, but it is still too slow.
I thought I could somehow use the same server Vuex on each call and sending it to the client with nuxtServerInit, but I don't see a way to achieve sharing the Vuex. Thank you for any pointers or other packages which could help.
The question is that after the fetch is finished after the api call in the server rendering, the DOM is dropped to the client, and the process is running every time and slow?
I solved similar issues using cookies. This is because cookies can also be used to render servers. I used the method below.
Store the data in the cookie after the initial api call, and send the data in the cookie to the client first.(If cookies are present, do not call api from server)
Call api from client to update data.
I use this library.
https://github.com/microcipcip/cookie-universal/tree/master/packages/cookie-universal-nuxt#readme

Is it a best practice to make setInterval every some seconds to re update axios request to update displayed data in vue project? [duplicate]

hi
I want to build a control panel for a web art application that needs to run in fullscreen, so all this panel, that controls stuff like colors and speed values, have to be located at a different window.
My idea is to have a database storing all these values and when I make a change in the control panel window the corresponding variable in the application window gets updated too. So, it's basically a real-time update that I could do with AJAX setting a interval to keep checking for changes BUT my problem is: I can't wait 30 seconds or so for the update to happen and I guess a every-1-second AJAX request would be impossible.
Final question: is there a way to create a sort of a listener to changes in the database and fire the update event in the main application only immediately after I change some value in the control panel? Does Angular or another framework have this capability?
(Sorry for the long explanation, but I hope my question is clearer by offering the context [: )
A web socket powered application would have this benefit. This carries a bit more complexity on the back end, but has the benefit of making your application as close to real-time as can be reasonably expected.
The Mozilla Development Network has some good documentation on websockets.
On the front end, the WebSocket object should work for you on most modern browsers.
I'm not sure what your back end is written in, but Socket.IO for Node.js and Tornado for Python will make your applications web-socket capable
If one window is opening the other windows via JavaScript, you can keep the reference to the opened window and use otherWindow.postMessage to pass messages across
"Parent" window looks like
// set up to receive messages
window.addEventListener('message', function (e) {
if (e.origin !== 'http://my.url')
return; // ignore unknown source
console.log(e.message);
});
// set up to send messages
var otherWindow = window.open('/foo', '_blank');
otherWindow.postMessage('hello world', 'http://my.url');
"Child" windows look similar
// same setup to recieve
// ...
// set up to send
var otherWindow = window.opener;
// ... same as before
For the realtime I would recommend using a library like socket.io or using a database like firebase.
For the fullscreen I would recommend using a library like angular-screenfull
i use https://pushjs.io/, had exactly the same problem and this is a really simple solution for your problem. It is capable of sending and listening to events without any database interference.

Flux without data caching?

Almost all examples of flux involve data cache on the client side however I don't think I would be able to do this for a lot of my application.
In the system I am thinking about using React/Flux, a single user can have 100's of thousands of the main piece of data we store (and 1 record probably has at least 75 data properties). Caching this much data on the client side seems like a bad idea and probably makes things more complex.
If I were not using Flux, I would just have a ORM like system that can talk to a REST API in which case a request like userRepository.getById(123) would always hit the API regardless if I requested that data in the last page. My idea is to just have the store have these methods.
Does Flux consider it bad that if I were to make request for data, that it always hit the API and never pulls data from a local cache instance? Can I use Flux in a way were a majority of the data retrieval requests are always going to hit an API?
The closest you can sanely get to no caching is to reset any store state to null or [] when an action requesting new data comes in. If you do this you must emit a change event, or else you invite race conditions.
As an alternative to flux, you can simply use promises and a simple mixin with an api to modify state. For example, with bluebird:
var promiseStateMixin = {
thenSetState: function(updates, initialUpdates){
// promisify setState
var setState = this.setState.bind(this);
var setStateP = function(changes){
return new Promise(function(resolve){
setState(changes, resolve);
});
};
// if we have initial updates, apply them and ensure the state change happens
return Promise.resolve(initialUpdates ? setStateP(initialUpdates) : null)
// wait for our main updates to resolve
.then(Promise.params(updates))
// apply our unwrapped updates
.then(function(updates){
return setStateP(updates);
}).bind(this);
}
};
And in your components:
handleRefreshClick: function(){
this.thenSetState(
// users is Promise<User[]>
{users: Api.Users.getAll(), loading: false},
// we can't do our own setState due to unlikely race conditions
// instead we supply our own here, but don't worry, the
// getAll request is already running
// this argument is optional
{users: [], loading: true}
).catch(function(error){
// the rejection reason for our getUsers promise
// `this` is our component instance here
error.users
});
}
Of course this doesn't prevent you from using flux when/where it makes sense in your application. For example, react-router is used in many many react projects, and it uses flux internally. React and related libraries/patters are designed to only help where desired, and never control how you write each component.
I think the biggest advantage of using Flux in this situation is that the rest of your app doesn't have to care that data is never cached, or that you're using a specific ORM system. As far as your components are concerned, data lives in stores, and data can be changed via actions. Your actions or stores can choose to always go to the API for data or cache some parts locally, but you still win by encapsulating this magic.

Flash player API for browser extension

let's say we have a P2P multi-player Flash based game hosted on a website. Would it be possible to create a browser extension that would listen to what is going on within the Flash application? For example, I would like to know when a player connects to a room, gets kicked or banned, or simply leaves by himself. I'm sorry this is not really a specific question but I need a direction to start. Thanks in advance!
I can see a few ways to communicate between Flash and a browser plugin.
One is to open a socket to a server running on the local machine. Because of the security sandbox, this may not be the easiest approach, but if feasible, it is of course probably the one to go for because you've already got your socket-handling code written, and listening/writing to a additional socket isn't terribly complicated. For this approach, you just need your plugin to start listening on a socket, and get the flash applet to connect to it.
Another way might be to try something with passing messages in cookies. Pretty sure this would just cause much grief, though.
Another way, and I suspect this may turn out to be the easier path, is to communicate between Flash and JavaScript using the ExternalInterface class, then from JavaScript to the plugin. Adobe's IntrovertIM example should get you started if you can find a copy on the web.
In Flash, create two functions, a jsToSwf(command:String, args:Array<String>):Dynamic function, to handle incoming messages from JS that are sent to that callback, and a swfToJs(command:String, args:Array<String> = null):Dynamic function, which calls flash.external.ExternalInterface.call("swfToJs", command, args);.
To set it up, you need to do something like:
if (flash.external.ExternalInterface.available) {
flash.external.ExternalInterface.addCallback("jsToSwf", jsToSwf);
swfToJs("IS JS READY?");
}
(The two parameters to addCallback are what the function is called in JS, and what it's called in Flash. They don't have to be the same thing, but it sort of makes sense that they do)
In JS, you need the same functions: function swfToJs(command, params) accepts commands and parameter lists from Flash; and jsToSwf(command, params) calls getSwf("Furcadia").jsToSwf(command, params);.
getSwf("name") should probably be something like:
/** Get ref to specified SWF file.
// Unfortunately, document.getElementById() doesn't
// work well with Flash Player/ExternalInterface. */
function getSwf(movieName) {
result = '';
if (navigator.appName.indexOf("Microsoft") != -1) {
result = window[movieName];
} else {
result = document[movieName];
}
return result;
}
The only fiddly bit there is that you need to do a little handshake to make sure everyone's listening. So when you have Flash ready, it calls swfToJs("IS JS READY?"); then the JS side, on getting that command, replies with jsToSwf("JS IS READY!"); then on getting that, Flash confirms receipt with swfToJs("FLASH IS READY!"); and both sides set a flag saying they're now clear to send any commands they like.
So, you've now got Flash talking with JS. But how does JS talk with a browser extension? And, do you mean extension, or add-on, since there's a difference! Well, that becomes a whole 'nother can of worms, since you didn't specify which browser.
Every browser handles things differently. For example, Mozilla has port.emit()/port.on() and the older postMessage() as APIs for JS to communicate with add-ons.
Still, I think ExternalInterface lets us reduce a hard question (Flash-to-external-code comms) to a much simpler question (Js-to-external-code comms).

Backbone.sync – Collection using ajax as well as Socket.IO/WebSockets

I have a Backbone application, which has a collection called Links. Links maps to a REST API URI of /api/links.
The API will give the user the latest links. However, I have a system in place that will add a job to the message queue when the user hits this API, requesting that the links in the database are updated.
When this job is finished, I would to push the new links to the Backbone collection.
How should I do this? In my mind I have two options:
From the Backbone collection, long poll the API for new links
Setup WebSockets to send a "message" to the collection when the job is done, sending the new data with it
Scrap the REST API for my application and just use WebSockets for everything, as I am likely to have more realtime needs later down the line
WebSockets with the REST API
If I use WebSockets, I'm not sure of the best way to integrate this into my Backbone collection so that it works alongside the REST API.
At the moment my Backbone collection looks like this:
var Links = Backbone.Collection.extend({
url: '/api/links'
});
I'm not sure how to enable the Backbone collection to handle AJAX and WebSockets. Do I continue to use the default Backbone.sync for the CRUD Ajax operations, and then deal with the single WebSocket connection manually? In my mind:
var Links = Backbone.Collection.extend({
url: '/api/links',
initialize: function () {
var socket = io.connect('http://localhost');
socket.on('newLinks', addLinks)
},
addLinks: function (data) {
// Prepend `data` to the collection
};
})
Questions
How should I implement my realtime needs, from the options above or any other ideas you have? Please provide examples of code to give some context.
No worries! Backbone.WS got you covered.
You can init a WebSocket connection like:
var ws = new Bakcbone.WS('ws://exmaple.com/');
And bind a Model to it like:
var model = new Backbone.Model();
ws.bind(model);
Then this model will listen to messages events with the type ws:message and you can call model.send(data) to send data via that connection.
Of course the same goes for Collections.
Backbone.WS also gives some tools for mapping a custom REST-like API to your Models/Collections.
My company has a fully Socket.io based solution using backbone, primarily because we want our app to "update" the gui when changes are made on another users screen in real time.
In a nutshell, it's a can of worms. Socket.IO works well, but it also opens a lot of doors you may not be interested in seeing behind. Backbone events get quite out of whack because they are so tightly tied to the ajax transactions...you're effectively overriding that default behavior. One of our better hiccups has been deletes, because our socket response isn't the model that changed, but the entire collection, for example. Our solution does go a bit further than most, because transactions are via a DDL that is specifically setup to be universal across the many devices we need to be able to communicate with, now and in the future.
If you do go the ioBind path, beware that you'll be using different methods for change events compared to your non-socket traffic (if you mix and match) That's the big drawback of that method, standard things like "change" becomes "update" for example to avoid collisions. It can get really confusing in late-night debug or when you have a new developer join the team. For that reason, I prefer either going sockets, or not, not a combination. Sockets have been good so far, and scary fast.
We use a base function that does the heavy lifting, and have several others that extend this base to give us the transaction functionality we need.
This article gives a great starter for the method we used.