我正在尝试使函数返回id是否为validId。
但是,有时候,即使await isValidId(230)
为true
,validId
也不是230。
我认为这是因为promises总是以异步方式解析。是对的吗?那我该怎么设计这个功能呢?
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 = []
}
答案 0 :(得分:2)
问题中的代码存在语法错误:它在非 (您已重新编辑代码以制作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
检查,等待playerHasItem
来电:
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;
};
通过最新的编辑,您已经建议在承诺解决后将某个播放器从在线阵列中删除。这告诉我,您在使用 canPlayerUseItem
的代码中了解如何知道播放器仍然在线。
答案:你不能。您在canPlayerUseItem
中执行的 Nothing 可以保护您免受此中固有的竞争条件的影响:
if (await canPlayerUseItem(player, itemId)) {
// They player may now be offline
}
...因为玩家可以在canPlayerUseItem
完成检查后但在消耗该结果的代码运行之前注销。这是异步代码的本质。以上基本上是这样的:
flag = canPlayerUseItem(player, itemId)
if (flag) ...
(此时播放器可能无法再登录)如果你需要进行检查,你必须自己在外面异步功能:
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
}
是:
flag = Database.playerHasItem(player, itemId)
if (flag && playersOnline.includes(player)
...