简体   繁体   中英

How do I wait for a callback to resolve a promise in JS? Sync iOS WKWebView and JS

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM