我试图使一个函数返回id是否为validId。
但是,事实证明,有时即使await isValidId(230)
是true
,validId
也不是230。
我认为这是因为承诺总是异步解决的。那正确吗?那我应该如何设计这个功能呢?
let validId = 230;
let isValidId = function(id){
return new Promise(resolve => {
//async code
resolve(validId === id);
});
}
if (await isValidId(230)){
//validId is not necessary 230
}
这是一个更完整的示例。
let playerAskedToLogOut = false;
let playersOnline = ['MyUsername'];
let canPlayerUseItem = async function(player,itemId){
let hasItem = await Database.playerHasItem(player, itemId);
let isStillOnline = playersOnline.includes(player);
playerAskedToLogOut = true; //normally called by another function
return hasItem && isStillOnline;
};
setInterval(() => {
useItems();
logOutPlayers();
}, 100);
let useItems = async function(){
if (await canPlayerUseItem('MyUsername', 'hammer')){
//the player is not online anymore. Yet, await canPlayerUseItem returned true
}
}
let logOutPlayers = function(){
if(playerAskedToLogOut)
playersOnline = []
}
最佳答案
问题中的代码存在语法错误:它在非await
函数中使用了async
,这是行不通的。 (您已再次编辑代码以制作canPlayerUseItem
async
)
第一:在new Promise
函数中使用async
根本没有任何目的。该功能自动为您创建一个承诺。因此该代码(在撰写本文时,您一直在对其进行更改)实际上应该是:
let canPlayerUseItem = async function(player,itemId){
let hasItem = await Database.playerHasItem(player, itemId);
let isStillOnline = playersOnline.includes(player);
return hasItem && isStillOnline;
};
canPlayerUseItem
的诺言将用true
解决的唯一原因是,当我们进行检查时,如果hasItem
返回真实且playersOnline
包含player
。 > ..如果播放器在呼叫playerHasItem
时不联机,但在canPlayerUserItem
检查完成时处于联机状态,则它将以playerHasItem
解析。如果要在等待
true
调用之前进行playersOnline
检查:let canPlayerUseItem = async function(player,itemId){
if (playersOnline.includes(player)) {
return false;
}
return await Database.playerHasItem(player, itemId);
};
或者,如果您想同时检查两者(但它们可能已脱机,则可以在两者之间重新联机):
let canPlayerUseItem = async function(player,itemId){
if (playersOnline.includes(player)) {
return false;
}
let hasItem = await Database.playerHasItem(player, itemId);
let isStillOnline = playersOnline.includes(player);
return hasItem && isStillOnline;
};
在您的最新编辑中,您建议在解决承诺后将某些东西从在线阵列中删除。这向我暗示您正在询问如何使用
playerHasItem
在代码中知道播放器仍处于在线状态。答:不能。您在
canPlayerUseItem
中所做的任何事情都不能保护您免受此内在的竞争状况的影响:if (await canPlayerUseItem(player, itemId)) {
// They player may now be offline
}
...因为玩家有可能在
canPlayerUseItem
完成检查之后但在消耗该结果的代码运行之前退出。这就是异步代码的本质。上面基本上是这样的:canPlayerUseItem
在此事件循环迭代结束之前的收益
flag = canPlayerUseItem(player, itemId)
(此时播放器可能不再登录)如果需要进行检查,则必须在异步函数之外自己进行检查:
if (await Database.playerHasItem(player, itemId) && playersOnline.includes(player)) {
// As of this event loop, the player is online, and had the item
// when we checked a moment ago
}
这是:
if (flag) ...
在此事件循环迭代结束之前的收益
flag = Database.playerHasItem(player, itemId)
...