【问题标题】:How do I wait for a callback to resolve a promise in JS? Sync iOS WKWebView and JS如何等待回调来解决 JS 中的承诺?同步 iOS WKWebView 和 JS
【发布时间】:2019-05-03 09:27:21
【问题描述】:

最近我一直在尝试实现我自己的LocalStorage 实现,但我没有将数据存储在 JS 中,而是尝试将数据存储在 iOS 本机端的 NSUserDefaults 中。我将向你展示一些代码以明确我在说什么。我自己的LocalStorage原型有这样的方法:

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);
};

getItem中我假设当客户端调用它时,它会等到iOS原生端从NSUserDefaults获取这个值并通过Storage.prototype.pasKeyValuePair方法将它传递给Storage。

但实际上看起来当sendWebKitMessage(LS_GET_ITEM, { key: key })被调用时,'线程'并没有被阻塞,客户端可以多次调用这个方法并且回调不能正常工作。

我是一个 JS 新手,我希望它会像互斥锁一样工作。这实际上可以在 JS 中实现,还是我在构建完全错误的东西。 我打算只使用 vanilla JS。

【问题讨论】:

    标签: javascript ios webkit wkwebview


    【解决方案1】:

    我想我明白你想做什么。如果我错了,请纠正我。 是的,我们可以在处理其他代码之前等待 Storage.getItem。但是,为此我们需要在调用 getItem 时使用 async-await。

    请检查此代码:

    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
    })();
    

    这不会等待 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");
    

    请查看@CodePenhttps://codepen.io/animatedcreativity/pen/5a295fc445f97022b75c37189bf875fd


    我无法测试你的代码。 但是,这是我能理解的。 我假设getValue 的承诺正在正确解决。 错误在于:var value = await getValue();。它不等待任何东西,因为它没有什么可等待的。它立即获得 Promise 对象。

    所以,请试试这个:

        var waitFuntion = (async function () {
            var value;
            await getValue().then(function(_value) {
                value = _value;
            });
            console.log("value="+value);
            return value;
        });
    

    这确保等到 getValue 的 Promise 实际解析该值。

    【讨论】:

    • 是的,你是对的。谢谢!但是实际上是否有可能阻塞Storage.prototype.getItem方法的洞,所以任何下一次调用它都会被阻塞,直到上一次调用收到他对应键的值?
    猜你喜欢
    • 1970-01-01
    • 2021-02-07
    • 2023-04-06
    • 2021-11-09
    • 1970-01-01
    • 2017-05-25
    • 1970-01-01
    • 1970-01-01
    • 2021-12-26
    相关资源
    最近更新 更多