数组群体不存在于它们被添加的功能之外?
Array populations don't exist outside of function they were added in?
我是 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);
});
}
当我尝试为 "leaderScores[0]"
中的任何内容读取数据库列 "E_highscores" 时出现问题
readRecords("userData",{E_highscore:leaderScores[0]},function(records) {
但是因为数组在第一个函数之外是空的,所以数组中的那个位置是空的。在此先感谢您的帮助!
-室内
readRecords
是一个异步函数,对吗?
问题是您有竞争条件。这意味着代码需要以非常特定的顺序执行才能工作,但您目前无法控制该顺序。
在传递给 readRecords
的回调中,分数被推送到 leaderScore
。但是,在下一行(调用 readRecords
之后),您尝试再次调用 readRecords
,并在 内部 的回调中填充了一个值首先 readRecords
.
基本上,您的代码按以下顺序执行:
readRecords("userData",{},callback1)
readRecords("userData",{E_highscore:leaderScores[0]},callback2)
callback1()
callback2()
事实上,不能保证 callback1
会在 callback2
之前发生!
有很多工具可以解决这个异步排序问题,例如 Promises 等。我将选择最简单的选项,然后重新安排您的代码。这将创建嵌套回调,但就目前而言,它可以工作并且(希望)能帮助您了解这一原则的实际应用。
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
只会在 填充数组后 发生,之前不会发生。
这确实会引发其他可重用性问题。如果您以后想做更复杂的事情,或者添加更多回调,甚至可能是一个循环,该怎么办?好吧,那将是你的哈哈。但是如果你牢记我们在这里讨论的原则,你绝对可以成功地做到这一点:任何异步回调都可以在 任何 时间调用,所以请始终牢记这一点。
问问自己这个问题:如果在 1 毫秒、500 毫秒和 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));
我是 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);
});
}
当我尝试为 "leaderScores[0]"
中的任何内容读取数据库列 "E_highscores" 时出现问题readRecords("userData",{E_highscore:leaderScores[0]},function(records) {
但是因为数组在第一个函数之外是空的,所以数组中的那个位置是空的。在此先感谢您的帮助!
-室内
readRecords
是一个异步函数,对吗?
问题是您有竞争条件。这意味着代码需要以非常特定的顺序执行才能工作,但您目前无法控制该顺序。
在传递给 readRecords
的回调中,分数被推送到 leaderScore
。但是,在下一行(调用 readRecords
之后),您尝试再次调用 readRecords
,并在 内部 的回调中填充了一个值首先 readRecords
.
基本上,您的代码按以下顺序执行:
readRecords("userData",{},callback1)
readRecords("userData",{E_highscore:leaderScores[0]},callback2)
callback1()
callback2()
事实上,不能保证 callback1
会在 callback2
之前发生!
有很多工具可以解决这个异步排序问题,例如 Promises 等。我将选择最简单的选项,然后重新安排您的代码。这将创建嵌套回调,但就目前而言,它可以工作并且(希望)能帮助您了解这一原则的实际应用。
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
只会在 填充数组后 发生,之前不会发生。
这确实会引发其他可重用性问题。如果您以后想做更复杂的事情,或者添加更多回调,甚至可能是一个循环,该怎么办?好吧,那将是你的哈哈。但是如果你牢记我们在这里讨论的原则,你绝对可以成功地做到这一点:任何异步回调都可以在 任何 时间调用,所以请始终牢记这一点。
问问自己这个问题:如果在 1 毫秒、500 毫秒和 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));