Recently I have been trying to implement my own LocalStorage
implementation but instead of storing data in JS I'm trying to store data on iOS native side in NSUserDefaults
. I will show u some code to make clear what I'm talking about. I have such method for my own LocalStorage
prototype:
Storage.prototype.getItem = (function (key) {
var that = this;
var getValue = (function () {
return new Promise(resolve => {
// JS2Native request value for a specific key
sendWebKitMessage(LS_GET_ITEM, { key: key });
console.log("new Promise for key=" + key + " timeInMs=" + Date.now());
// create success callback
that.onKeyValueReceived = function (keyValuePair) {
if (keyValuePair !== null) {
console.log("onKeyValueReceived=" + keyValuePair.key + " value=" + keyValuePair.value);
resolve(keyValuePair.value);
}
else {
console.log("onKeyValueReceived=null for=" + key);
resolve(null);
}
};
});
});
// handle async response from the Native side
var waitFuntion = (async function () {
var value = await getValue();
console.log("value="+value);
return value;
});
return waitFuntion();
});
// Native2JS helper methods
Storage.prototype.pasKeyValuePair = function (key, value) {
this.onKeyValueReceived(key, value);
};
In getItem
I assume that when a client is calling it, it will wait until the iOS native side will get this value from NSUserDefaults
and pass it to Storage via Storage.prototype.pasKeyValuePair
method.
But actually it look like that when sendWebKitMessage(LS_GET_ITEM, { key: key })
is called the 'thread' is not blocked and the client can call this method several time more and the call back is not working properly.
I'm a JS newbie guy, I expected that it will work like a mutex. Is this actually possible to implement in JS or am I building something this completely wrong. I plan to do it using only vanilla JS.
I think I understand what you want to do. Please correct me if I am wrong. Yes, we can wait for Storage.getItem before processing other code. But, for this we need to use async-await when calling getItem.
Please check this code:
var Storage = function() {};
Storage.prototype.getItem = function(key) {
var promise = new Promise(function(resolve, reject) {
//Fetch your item here and resolve the value. setTimeout is just for example.
setTimeout(function() {
resolve("Some value goes here.");
}, 2000);
});
return promise;
};
(async function() {
var storage = new Storage();
console.log("I am called BEFORE Storage.getItem");
var item = await storage.getItem("key");
console.log(item);
console.log("I am called AFTER Storage.getItem");
console.log("Storage.getItem second time");
item = await storage.getItem("key");
console.log(item);
//do something else
})();
This is not going to wait for Storage.getItem:
var storage = new Storage();
console.log("I am called BEFORE Storage.getItem");
var item = storage.getItem("key");
console.log(item);
console.log("I am called AFTER Storage.getItem");
Please check @ CodePen https://codepen.io/animatedcreativity/pen/5a295fc445f97022b75c37189bf875fd
I cannot test your code.
But, here is what I can understand.
I am assuming that getValue
's Promise is resolving properly.
Mistake is with the line: var value = await getValue();
. Its not waiting for anything because it has nothing to wait. Its getting the Promise object right away.
So, please try this:
var waitFuntion = (async function () {
var value;
await getValue().then(function(_value) {
value = _value;
});
console.log("value="+value);
return value;
});
This makes sure to wait till getValue
's Promise actually resolves the value.