Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/arrays/12.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_Arrays_For Loop_App Lab - Fatal编程技术网

Javascript 数组总体不';它们是否不存在于添加到的功能之外?

Javascript 数组总体不';它们是否不存在于添加到的功能之外?,javascript,arrays,for-loop,app-lab,Javascript,Arrays,For Loop,App Lab,我对JavaScript非常陌生,遇到了一个我找不到解决方案的问题。我正在为我的APCS最终项目开发一个游戏,我正在尝试为它添加一个排行榜。为了找到排名靠前的玩家,我将所有高分放在一个数组中,从最大到最小排序,然后搜索5个得分与数组中前5个数字匹配的用户名。我正在使用AppLab创建它,AppLab有一个内置的数据库功能,这就是“readRecords”的用途。不过,我的问题是,当我用for循环填充数组时,即使数组变量是在函数外部创建的,填充也不存在于函数外部,下面是代码 function le

我对JavaScript非常陌生,遇到了一个我找不到解决方案的问题。我正在为我的APCS最终项目开发一个游戏,我正在尝试为它添加一个排行榜。为了找到排名靠前的玩家,我将所有高分放在一个数组中,从最大到最小排序,然后搜索5个得分与数组中前5个数字匹配的用户名。我正在使用AppLab创建它,AppLab有一个内置的数据库功能,这就是“readRecords”的用途。不过,我的问题是,当我用for循环填充数组时,即使数组变量是在函数外部创建的,填充也不存在于函数外部,下面是代码

function leaderGrabEasy() {
  var leaderScores = [];
  var leaders = [];
  readRecords("userData",{},function(records) {
    for (var i = 0; i < records.length; i++) {
      leaderScores.push(records[i].E_highscore);
    }
    leaderScores.sort(function(a, b){return b-a});
  });
  readRecords("userData",{E_highscore:leaderScores[0]},function(records) {
    for (var i = 0; i < records.length; i++) {
      leaders.push(records[i].username);
    }
    console.log(leaders);
  });
}
但是因为数组在第一个函数之外是空的,所以数组中的那个点是空的。提前感谢您的帮助


-室内

读取记录是一个异步功能,对吗

问题是您有一个竞态条件,这意味着代码需要按照非常特定的顺序执行才能工作,但您目前无法控制该顺序

分数被推送到传递给
readRecords
的回调中的
leaderScore
。但是,在下一行(调用
readRecords
之后),您尝试再次调用
readRecords
,并在回调中填充一个值,以调用第一个
readRecords

基本上,您的代码按以下顺序执行:

readRecords("userData",{},callback1)
readRecords("userData",{E_highscore:leaderScores[0]},callback2)
callback1()
callback2()
事实上,不能保证
callback1
会在
callback2
之前发生

有很多工具可以解决这个异步排序问题,比如承诺之类的。我将使用最简单的选项,重新排列代码。这将创建嵌套回调,但就目前而言,它可以工作,并且(希望)可以帮助您看到这一原则的实际应用

function leaderGrabEasy() {
  var leaderScores = [];
  var leaders = [];
  readRecords("userData",{},function(records) {
    for (var i = 0; i < records.length; i++) {
      leaderScores.push(records[i].E_highscore);
    }
    leaderScores.sort(function(a, b){return b-a});

    readRecords("userData",{E_highscore:leaderScores[0]},function(records) {
     for (var i = 0; i < records.length; i++) {
        leaders.push(records[i].username);
     }
    console.log(leaders);
     });
  });
}
函数leaderGrabEasy(){
var领导核心=[];
var leaders=[];
readRecords(“userData”,{},函数(记录){
对于(var i=0;i
现在,第二个
readRecords
只会在填充数组之后发生,而不是之前的任何时候


这确实带来了可重用性方面的其他问题。如果您以后想做更复杂的事情,或者添加更多回调,甚至可能是一个循环,该怎么办?好吧,这将取决于您哈哈。但是如果您记住我们在这里讨论的原则,您肯定可以成功地做到这一点:任何异步回调都可以在任何时间调用很明显,所以要时刻牢记这一点,纠正代码


问自己这样一个问题:如果这个回调被内联调用(同步地,按照编写顺序),我的代码会工作吗,在1ms、500ms和1分钟内?如果是这样,那么它在逻辑上是合理的。

最好将函数转换为承诺返回函数,而不是嵌套回调。现在代码可能很容易维护,但当您编写的代码越来越多时,将很难解开后记

//readRecords as a promise returning function
function readAsPromise(str,obj){
  return new Promise(
    function (resolve,reject){
      readRecords(
        str,
        obj,
        function(records,error) {//this readRecords cannot fail?
          if(error){
            reject(error);return;
          }
          resolve(records);
        }
      );
    }
  );
}

function leaderGrabEasy() {
  return Promise.all([
    readRecords("userData",{}),
    readRecords("userData",{E_highscore:leaderScores[0]})
  ])
  .then(
    function(results){
      return {
        leaderScores:results[0]
          .map(function(leader){return leader.E_highscore;})
          .sort(function(a, b){return b-a}),
        leaders:results[1]
          .map(function(leader){return leader.username})
      }
    }
  )
}

//use the function:
leaderGrabEasy()
.then(
  function(result){
    console.log("result:",result);
  }
)
.catch(
  function(error){
    console.log("there was an error:",error);
  }
)

//arrow function syntax:
leaderGrabEasy()
.then(result=>console.log("result:",result))
.catch(error=>console.log("there was an error:",error));
在现代语法中,它将如下所示:

//readRecords as a promise returning function
const readAsPromise = (str,obj) =>
  new Promise(
    function (resolve,reject){
      readRecords(
        str,
        obj,
        function(records,error) {//this readRecords cannot fail?
          if(error){
            reject(error);return;
          }
          resolve(records);
        }
      );
    }
  );

const leaderGrabEasy = () =>
  Promise.all([
    readRecords("userData",{}),
    readRecords("userData",{E_highscore:leaderScores[0]})
  ])
  .then(
    ([score,name])=>({
      leaderScores:score.map(leader=>leader.E_highscore).sort((a, b)=>b-a),
      leaders:name.map(name=>nae.username)
    })
  )

//use the function:
leaderGrabEasy()
.then(result=>console.log("result:",result))
.catch(error=>console.log("there was an error:",error));

非常感谢的可能重复,直到现在我还不知道异步函数是什么,尽管我确实想象了一些类似的问题,再一次,谢谢!而且,我现在正在实现驱动排行榜的代码,多亏了你,它应该可以工作。我已经将你添加到积分中:)goo.gl/ZHeeeH@Indoors啊,太好了nks!很高兴你也能学到一些新东西:)非常感谢你的帮助,但这是另一个层面,除非我完全理解它,否则我不会使用它,这需要一段时间。
//readRecords as a promise returning function
const readAsPromise = (str,obj) =>
  new Promise(
    function (resolve,reject){
      readRecords(
        str,
        obj,
        function(records,error) {//this readRecords cannot fail?
          if(error){
            reject(error);return;
          }
          resolve(records);
        }
      );
    }
  );

const leaderGrabEasy = () =>
  Promise.all([
    readRecords("userData",{}),
    readRecords("userData",{E_highscore:leaderScores[0]})
  ])
  .then(
    ([score,name])=>({
      leaderScores:score.map(leader=>leader.E_highscore).sort((a, b)=>b-a),
      leaders:name.map(name=>nae.username)
    })
  )

//use the function:
leaderGrabEasy()
.then(result=>console.log("result:",result))
.catch(error=>console.log("there was an error:",error));