Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/csharp-4.0/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 不正确的承诺返回值_Javascript_Promise - Fatal编程技术网

Javascript 不正确的承诺返回值

Javascript 不正确的承诺返回值,javascript,promise,Javascript,Promise,我试图让一个函数返回一个id是否为有效id。 然而,事实证明,有时,即使wait isValidId(230)是true,validId也不是230 我认为这是因为承诺总是异步解决的。是这样吗?那么我该如何设计这个功能呢 let validId = 230; let isValidId = function(id){ return new Promise(resolve => { //async code resolve(validId === id); }); }

我试图让一个函数返回一个id是否为有效id。 然而,事实证明,有时,即使
wait 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 = []
}
问题中的代码有一个语法错误:它在非
async
函数中使用
await
,该函数不起作用。(您已再次编辑代码以使
canplayerSeItem
async

第一:在
async
函数中使用
newpromise
毫无意义。该函数自动为您创建承诺。因此,代码(在撰写本文时,您一直在更改它)实际上应该是:

let canPlayerUseItem = async function(player,itemId){
  let hasItem = await Database.playerHasItem(player, itemId);
  let isStillOnline = playersOnline.includes(player);
  return hasItem && isStillOnline;
};
canplayerseitem
的承诺将以
true
解决的唯一原因是
hasItem
返回truthy并且
playersOnline
包含
player
在我们等待
playershitem
之后的检查。。如果在您调用
canPlayerUserItem
时播放机未联机,但在
playerHasiItem
检查完成时播放机联机,则将使用
true
进行解析

如果要在等待
playerHasItem
之前执行
playerOnline
检查,请呼叫:

let canPlayerUseItem = async function(player,itemId){
  if (playersOnline.includes(player)) {
    return false;
  }
  return await Database.playerHasItem(player, itemId);
};
或者,如果您想同时检查两个(但它们可能已脱机,然后在两者之间重新联机):


在您最近的编辑中,您建议在承诺解析之后将播放器从在线阵列中删除。这向我表明,您正在询问如何使用
canplayerseitem
在代码中知道播放器仍然在线

回答:你不能您在
canplayerseitem
中所做的任何事情都不能保护您免受以下情况固有的竞争条件的影响:

if (await canPlayerUseItem(player, itemId)) {
    // They player may now be offline
}
…因为玩家可以在
CanPlayerSeItem
完成检查后,但在您的代码运行之前注销该结果。这就是异步代码的本质。以上基本上是这样的:

  • flag=canplayerseitem(玩家,项目ID)
  • 直到该事件循环迭代结束时为止
  • 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)
  • 问题中的代码有一个语法错误:它在非
    async
    函数中使用
    await
    ,该函数不起作用。(您已再次编辑代码,使
    canplayerseitem
    async

    第一:在
    异步
    函数中使用
    新承诺
    毫无意义。该函数会自动为您创建承诺。因此,代码(在撰写本文时,您一直在更改它)实际上应该是:

    let canPlayerUseItem = async function(player,itemId){
      let hasItem = await Database.playerHasItem(player, itemId);
      let isStillOnline = playersOnline.includes(player);
      return hasItem && isStillOnline;
    };
    
    canplayerseitem
    的承诺将以
    true
    解决的唯一原因是
    hasItem
    返回truthy并且
    playersOnline
    包含
    player
    我们执行该检查时,即我们等待
    playershitem
    之后的之后。如果玩家在u调用
    canPlayerUserItem
    ,但当
    playerHitem
    检查完成后,它将以
    true
    进行解析

    如果要在等待
    playerHasItem
    之前执行
    playerOnline
    检查,请呼叫:

    let canPlayerUseItem = async function(player,itemId){
      if (playersOnline.includes(player)) {
        return false;
      }
      return await Database.playerHasItem(player, itemId);
    };
    
    或者,如果您想同时检查两个(但它们可能已脱机,然后在两者之间重新联机):


    在您最近的编辑中,您建议在承诺解析之后从联机阵列中删除播放机。这向我表明,您正在询问如何使用
    canplayerseitem
    在代码中知道播放机仍然联机

    回答:你不能。你在
    canplayerseitem
    中所做的任何事情都不能保护你免受以下固有的种族状况的影响:

    if (await canPlayerUseItem(player, itemId)) {
        // They player may now be offline
    }
    
    …因为玩家可以在
    CanPlayerSeItem
    完成检查后,但在您的代码使用结果运行之前注销。这是异步代码的本质。上面基本上是这样的:

  • flag=canplayerseitem(玩家,项目ID)
  • 直到该事件循环迭代结束时为止
  • 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)

  • 为什么
    isValidId
    是异步的?分别:它真正的目的是什么?我想你必须向我们展示你的真实代码,包括异步代码,因为问题可能不在你在这里展示的代码中。什么是
    //异步代码
    ?为什么
    isValidId
    是异步的?分别:它真正的目的是什么?我想你会我必须向我们展示你的真实代码,包括异步代码,因为问题可能不在你在这里展示的代码中。什么是
    //异步代码
    ?@RainingChain-问题的更新并不会真正改变答案:如果
    hasItem
    是真实的,并且玩家仍然在线,它将用
    true
    解决(例如,仍在
    PlayerOnline
    阵列中)自