I am building a Chrome Extension that requires Parse User sessions. Because localstorage is domain specific, I need to use chrome.storage so it can be accessed while on any site.
The current Parse Javascript SDK uses localstorage to store a user object and create sessions. How can I switch this so Parse uses chrome.storage?
Here's my current thinking atm:
on login
store sessiontoken in chrome.storage
Then when I visit a site:
if chrome.storage.sessiontoken
create parse session with chrome.storage.sessiontoken
I was wondering if anyone's come across a simpler way?
I would love to just do:
window.localstorage = chrome.storage
But imagine that will lead to problems. Anyone solved this?
Basically you need to write your own storage controller(with chrome api ofcourse) and then let parse to use it.
Since this thread is newer, here's the detailed solution:
By default, Parse javascript SDK use window.localStorage api to store data.
However, in Chrome app, localStorage is replaced by chrome.storage api, which offers better non-blocking storage solution.
Parse SDK is actually prepared for different type of storage(both sync and async), and let your set your own custom storage controller
As #andrewimm (from github) pointed out, you need to call Parse.CoreManager.setStorageController(YOUR_STORAGE_CONTROLLER) before you call Parse.initialize.
An example custom storage controlled is Parse React Native storage controller( which is also async), which could be found at: https://github.com/ParsePlatform/Parse-SDK-JS/blob/master/src/StorageController.react-native.js
A Sync controller object need to set its async property to 0, and have
getItem, setItem,removeItem, and clear function implemented
An Async controller object need to set async property to 1, and have getItemAsync, setItemAsync,removeItemAsync,clearimplemented
All you need to do is to follow the react native example and build yourself your own storage controller (with chrome storage api), and let Parse to use it instead of use localStorage
Original Github issue thread:https://github.com/ParsePlatform/Parse-SDK-JS/issues/72
You can't directly substitute localstorage with chrome.storage, because one is synchronous and one is not, not to mention different API methods.
You cannot anyhow wrap it in a way that it becomes fully synchronous. However, here are some ideas:
Work with storage in the background script. There, the domain for localStorage is fixed.
Make a local synchronous copy of the storage; something like
var localData = {};
chrome.storage.local.get(null, function(data) {
localData = data;
doSomethingElse(); // Mind that this is async
})
However, saving this cache is going to be a problem. You have to intercept writes and commit it to chrome.storage and likewise update it on onChanged event - but all that will be asynchronous, which may not work.
In short, if a library uses localStorage internally, you won't be able to replace it adequately without rewriting the library or keeping it to background.
Related
Can we use the JavaScript FileSystemAPI from a webworker?
https://developer.mozilla.org/en-US/docs/Web/API/FileSystem
In their documentation they have not mentioned anything but while using it its throwing window not defined.
Thanks!
Not really...
There used to be a self.webkitRequestFileSystemSync() method accessible in Worker scopes, but it's been deprecated. And the FileSystem object you'd get from a drop event can't be serialized, and thus can't be posted to Worker from the main thread.
However, I suspect you don't really want to work with the FileSystem API, which is not really useful in web contexts, but instead you may want to prefer the File System Access API, which gives your page access to the user's file system (even though it's still only available in Chromium based browsers).
But to use this API from a Web Worker is not simple either.
To make the request to the File System Access API, we need to be handling an user-gesture. Web Workers don't have access to the UI and thus they don't either have access to UI events (yet).
So we must make the request from the UI thread.
However, contrary to FileSystem objects, FileSystemHandles are serializable and can be posted though postMessage(), so once you get the handle, you can post it to your worker and do your work from there.
In UI thread
btn.onclick = async (evt) => {
const dirHandle = await showDirectoryPicker();
worker.postMessage( dirHandle );
};
Then in the Worker thread you can receive that handle in the MesageEvent.data, and work with it as you'd do from the main thread.
Here is a live demo, and its source.
Webworkers global object name is global, not window.
And there is no FileSystem API
I've been working with React for a little while, and after some time i started to ask myself, why not store every piece of data that my components need to share in localstorage instead of using Redux. Redux need so much boilerplate while localstorage is so simple. You can say that you cant storage object in localstorage but you can JSON.stringfy them, and on recovery just parse them back. So problaby there's something that i cant see properly about that, cause Redux is largely used and localstorage is normally used just to save data you dont wish to loss on refresh and things like that.
This question was on my head when I started developing react apps.
There are many reasons than below to use redux over localStorage.
but at least
Using Redux alongside react-redux is not only for store data. don't forget that changing in a state will reRender All components that listen to that state. and that is really what react-redux does.
stringify/parse from localStorage will make your app (on high-scale) slower and also will not sync all components while changing state.
Personal Recommendation After more than 4 years of developing React Apps, use REDUX with easy API like redux-toolkit or rematch
Redux and localStorage have different use cases actually. Redux you'll use to manage your application state across multiple components.
Local Storage you'll use to persist properties in the browser for later usage. The problem is that any change on your localStorage won't reflect on your application. You'll have to do it manually.
The purpose of react-redux is to allow other components to connect to state and then react on changes. You are loosing the whole scope of using react-redux/context api.
The answer is in your question, yes local storage is only used for storing data in the browser while redux and context api solve some different problem. It separates your data layer from your view to easily manage your data state. If the app is not really big then you should consider going with Context API.
You can read this article for more info.
Note, stringifying and parsing itself is a pretty heavy operations for larger datasets.
It's probably OK to use localstorage instead of Redux. It's possible to have changes in localstorage have immediate effect on subscribed react components.
The people at marmelab who built react-admin transitioned from using redux to what they call The Store.
React-admin contains a global, synchronous, persistent store for
storing user preferences. Think of the Store as a key-value database
that persists between page loads.
The store uses the browser local storage (or a memory storage when
localStorage isn’t available). The store is emptied when the user logs
out.
When using react-admin changes in localstorage have immediate effect on subscribed react components. Checkout the readme and try the demo. Do some fiddling with data in localstorage manually, and see how react components rerender. I was amazed when I saw that for the first time.
I think it's ok. It depends on your requirement. In our situation, we need to split a big project into several small projects, whether use Redux or Mobx both cause problem very difficult, so we totally remove Redux and Mobx, just use LocalStorage to save all states. We know it will be slow and cannot rerender when state changes, but we want to accept it, and even add a Refresh button on some page if need to get state from local storage. So the answer is: it's ok to totally remove Redux, just see if you want to accept it or not.
Why use Redux instead of localStorage:
Disk space: You will probably not be deleting data from local storage every time the user quits your website. (you could with onbeforeonunload event enter link description here but it doesn't look like a good pracitce).
Security: If you are saving user's data, you would have to be careful on not mixing users data saved on localStorage.
Why not use Redux instead of localStorage:
"update the state": The truth is that you can listen to changes on localStorage and then change the state. So, I think, this is not a good reason. For example:
window.addEventListener('storage', (event) => { setState("changed")});
Simplicity: as Zhang Buzz, redux can be a pain.
Each case is different and you'll needs to weight the pros and cons to make a good decision.
We are currently exploring some of the undocumented apis in Relay Modern, and so far the best way we have found to grab data out of the Relay Store for use in the application is to call environment.lookup with a selector derived from a graphql query.
this happened because it seems like the RecordSource.get method returns the object from the store but doesn't fetch any data for nodes nested under it. Is there a better way to fetch an object and all connected nodes to it?
Our use case is we are using applyOptimisticUpdate to update Relay's store so that changes that are made prior to saving on our admin application are visible to all components that have requested that piece of data. So once we are done making these changes we'd like to requery the relay Store to get the current state of a record, clean it up for real mutation purposes, and send the updated payload to the server.
Any insights would be appreciated and I will add documentation to Relay with findings (if so desired).
Relay exposes a commitLocalUpdate function, which takes the environment and an updater function as arguments. The updater works the same way as the ones you use in mutations -- it receives a proxy of the store which you can modify and return. You could use the body of this function to read data from the store and emit any side-effects you need.
It feels a bit like abusing the API though, so there's probably a more correct way of doing this.
I have a long javascript function (about 72k minified) that is required on several pages of my site. My existing method to employ the function on my pages is to call the script by the usual means:
<script type="text/javascript" src="./javascript/complex_function.js"></script>
However, this involves reading and parsing the script on each page on which it is required. If I could store the function in my browser's memory and simply call it from there, then it would seem more efficient and faster (yes?)
Sadly, it seems that sessionStorage only supports the storages of keys and values that are strings. I've tried stringifying the function (as discussed elsewhere re: Javascript objects being stored in sessionStorage or localStorage), like so:
// First call the function in an initial page of the site:
<script type="text/javascript" src="./javascript/complex_function.js"></script>
// Then stringify it and store in sessionStorage:
sessionStorage.setItem('my_function', JSON.stringify(my_function));
Thereafter, in theory, I should be able to retrieve the function from sessionStorage anywhere session is active on my site, like this:
var temp = JSON.parse(sessionStorage.getItem('my_function');
...although (1) this doesn't work, or at least I can't find a way to make it work, and (2) even if I could make it work, it would still involve parsing the function, which would defeat the purpose (right?)
So...what is the best way to store a Javascript function in memory (no cookies, please) so that it can be called from any page on my site? (Or is this possible at all?)
Your browser will already do this for you. It will cache scripts upon their first download to reduce loading times, so once it's loaded the first time successive requests for that file will be quicker as it is pulled from the local machine, not the server.
first of all, I don't think it's a good idea to store js functions in memory.
And per my experiences, the sessionStorage only store string values, so you can try eval()
If I write a plugin which requires a very large initialization (14 mb JavaScript which takes 1 minute to set itself up), how can I make this object persistent (for lack of a better word) across the JavaScript files used in a Meteor projects?
After the initialization of the plugin, I have an object LargeObject and when I add a file simple_todo.js, I want to use LargeObject without it taking a minute to load after EVERY change.
I cannot find any solution.
I tried making a separate package to store this in Package object, but that is cleared after every change and reinitialized.
What would be the proper way of doing that? I imagine there should be something internal in Meteor which survives hot code push.
Here are two possible solutions I:
Cache some of its properties inside Session
Cache some of its properties inside a simple collection
Use a stub in your local environment.
Session can only be used client side. You can use a collection anywhere.
Session
client
example = function () {
if(!(this.aLotOfData = Session.get('aLotOfData'))) {
this.aLotOfData = computeALotOfData()
Session.set('aLotOfData', this.aLotOfData)
}
}
Here, no data has to be transferred between client and server. For every new client that connects, the code is rerun.
Collection
lib
MuchDataCollection = new Mongo.Collection('MuchDataCollection')
server
Meteor.publish('MuchData', function (query) {
return MuchDataCollection.find(query)
})
server
example = function () {
if(
!this.aLotOfData = MuchDataCollection.findOne({
name: 'aLotOfData'
}).data
) {
this.aLotOfData = computeALotOfData()
MuchDataCollection.insert({
name: 'aLotOfData',
data: this.aLotOfData
})
}
}
Even dough you can access the collection anywhere, you don't want anyone to be able to make changes to it. Because all clients share the same collection. Collections are cached client side. Read this for more info.
Stub
A stub is probably the easiest to implement. But it's the worst solution. You'll probably have to use a settings variable and still end up having the code for the stub inside the production environment.
What to choose
It depends on your exact use-case. If the contents of the object depend on the client or user, it's probably best to use a session-var. If it doesn't go for a collection. You'll probably need to build some cache-invalidation mechanisms, but I'd say, it's worth it.