我如何等待回调来解决 JS 中的承诺?同步 iOS WKWebView 和 JS
How do I wait for a callback to resolve a promise in JS? Sync iOS WKWebView and JS
最近我一直在尝试实现我自己的 LocalStorage
实现,但我没有在 JS 中存储数据,而是试图在 NSUserDefaults
中的 iOS 本机端存储数据。我将向您展示一些代码以阐明我在说什么。我自己的 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
方法。
但实际上调用sendWebKitMessage(LS_GET_ITEM, { key: key })
时,'thread'没有被阻塞,客户端可以多次调用此方法,但回调无法正常工作。
我是 JS 新手,我希望它能像互斥锁一样工作。这实际上有可能在 JS 中实现,还是我构建的东西完全错误。
我打算只使用香草 JS 来做。
我想我明白你想做什么。如果我错了,请纠正我。
是的,我们可以等待 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");
请查看@CodePen https://codepen.io/animatedcreativity/pen/5a295fc445f97022b75c37189bf875fd
我无法测试您的代码。
但是,这是我能理解的。
我假设 getValue
的 Promise 正在正确解决。
错误在于行: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 实际解析该值。
最近我一直在尝试实现我自己的 LocalStorage
实现,但我没有在 JS 中存储数据,而是试图在 NSUserDefaults
中的 iOS 本机端存储数据。我将向您展示一些代码以阐明我在说什么。我自己的 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
方法。
但实际上调用sendWebKitMessage(LS_GET_ITEM, { key: key })
时,'thread'没有被阻塞,客户端可以多次调用此方法,但回调无法正常工作。
我是 JS 新手,我希望它能像互斥锁一样工作。这实际上有可能在 JS 中实现,还是我构建的东西完全错误。 我打算只使用香草 JS 来做。
我想我明白你想做什么。如果我错了,请纠正我。 是的,我们可以等待 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");
请查看@CodePen https://codepen.io/animatedcreativity/pen/5a295fc445f97022b75c37189bf875fd
我无法测试您的代码。
但是,这是我能理解的。
我假设 getValue
的 Promise 正在正确解决。
错误在于行: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 实际解析该值。