[英]Incorrect Promise return value
I'm trying to make a function returns whether an id is the validId. 我试图使函数返回id是否为validId。 However, it turns out that sometimes, even if await isValidId(230)
is true
, validId
is not 230. 但是,事实证明,有时即使await isValidId(230)
为true
, validId
也不为230。
I assume this is because promises are always resolved asynchronously. 我认为这是因为承诺总是异步解决的。 Is that right? 那正确吗? How am I supposed to design this function then? 那我应该如何设计这个功能呢?
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
}
Here's a more complete example. 这是一个更完整的示例。
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 = []
}
The code in the question has a syntax error: It's using await
in a non- async
function, which doesn't work.问题中的代码存在语法错误:它在非 (You've edited the code again to make async
函数中使用了await
,这是行不通的。canPlayerUseItem
async
) (您再次编辑了代码以使canPlayerUseItem
async
)
First: There's no purpose at all in using new Promise
within an async
function. 第一:在async
函数中使用new Promise
根本没有任何目的。 The function creates a promise for you automatically. 该功能自动为您创建一个承诺。 So that code (as of this writing, you keep changing it) really should be just: 因此该代码(在撰写本文时,您一直在对其进行更改)实际上应该是这样的:
let canPlayerUseItem = async function(player,itemId){
let hasItem = await Database.playerHasItem(player, itemId);
let isStillOnline = playersOnline.includes(player);
return hasItem && isStillOnline;
};
The only reason canPlayerUseItem
's promise would resolve with true
would be if hasItem
comes back truthy and playersOnline
contains player
as of when we do that check, which is after we've waited for playerHasItem
.. If the player is not online when you call canPlayerUserItem
but is online when the playerHasItem
check has completed, it will resolve with true
. canPlayerUseItem
会按true
解析的唯一原因是,如果hasItem
返回真实值,并且playersOnline
包含我们执行该检查时的player
,即在我们等待playerHasItem
。 canPlayerUserItem
但在线时playerHasItem
检查已经完成,它会与解决true
。
If you want to do the playersOnline
check before waiting for the playerHasItem
call: 如果要在等待playerHasItem
调用之前进行playersOnline
检查:
let canPlayerUseItem = async function(player,itemId){
if (playersOnline.includes(player)) {
return false;
}
return await Database.playerHasItem(player, itemId);
};
Or if you want to check both (but they could have gone offline, then come back online, in-between): 或者,如果您想同时检查两者 (但它们可能已经脱机,则可以在两者之间重新联机):
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;
};
With your latest edit, you've suggested that something is removing the player from the online array after the promise resolution. 在您的最新编辑中,您建议在解决承诺后将某些东西从在线阵列中删除。 That suggests to me that you're asking about how you can know the player is still online in the code using canPlayerUseItem
. 这向我暗示您正在询问如何使用 canPlayerUseItem
在代码中知道播放器仍处于在线canPlayerUseItem
。
Answer: You can't. 答:不能。 Nothing you do in canPlayerUseItem
can protect you from the race condition inherent in this: 您在canPlayerUseItem
中canPlayerUseItem
任何事情canPlayerUseItem
不能保护您免受此内在的竞争条件的影响:
if (await canPlayerUseItem(player, itemId)) {
// They player may now be offline
}
...because it's possible for the player to sign out after canPlayerUseItem
has done its check but before your code consuming that result runs. ...因为播放器有可能在canPlayerUseItem
完成检查之后但在消耗该结果的代码运行之前退出。 This is the nature of asynchronous code. 这就是异步代码的本质。 The above is basically this: 上面基本上是这样的:
flag = canPlayerUseItem(player, itemId)
if (flag) ...
(at which point the player may no longer be logged in) if (flag) ...
(此时玩家可能不再登录) If you need to do that check, you'll have to do it yourself outside the asynchronous function: 如果需要进行检查,则必须在异步函数之外自己进行检查:
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
}
which is: 这是:
flag = Database.playerHasItem(player, itemId)
if (flag && playersOnline.includes(player)
... if (flag && playersOnline.includes(player)
...
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.