Javascript:顺序,不是并行
Javascript: sequential, not parallel
我正在做一个项目,但无法让我的 javascript 按顺序工作。我知道 javascript 可以并行执行任务,因此当您向不响应的服务器发出请求时它不会卡住。这有它的优点和缺点。就我而言,这是一个痛苦的流浪汉。
场景如下,我使用 Firebase 来存储有多少人同意某个观点。这看起来如下:
我喜欢javascript
- 非常喜欢
- 我喜欢
- 喜欢或不喜欢它
- 不喜欢
- 我基本上讨厌它
人们现在可以 select 1 个选项。然后将他们的 selection 的记录放在选项下。结构:
-dfd21DeH67 : {
Title : "I like javascript"
options : {
0 : {
option : "I like it a lot"
agrees : {
-dfd21DQH6sq7 : "Jhon"
-dfd21DQH6sq8 : "Luke"
-dfd21DQH6sq9 : "Bruce"
}
}
1 : {
option : "I like it"
agrees : {
-dfd21DQH6sqA : "Harry"
-dfd21DQH6sqB : "Jimmy"
}
}
2 : {
option : "like nor dislike it"
agrees : {
-dfd21DQH6sqC : "Timmy"
-dfd21DQH6sqD : "Paul"
-dfd21DQH6sqE : "Danny"
-dfd21DQH6sqF : "Robin"
-dfd21DQH6sqG : "Dan"
}
}
3 : {
option : "don't like it"
agrees : {
-dfd21DQH6sqH : "Nathan"
-dfd21DQH6sqI : "Jerry"
}
}
4 : {
option : "I basically hate it"
agrees : {
-dfd21DQH6sqJ : "Tony"
}
}
}
}
现在,我想查询一下。我需要的每个选项的结果是:
- 选项(例如 "I like it a lot")
- 同意计数(例如 n 人同意这个)
- 百分比(例如,13 人中有 3 人说:"I like javascript"。这将是 ~23%)
现在,获取 "option" 并在浏览器中显示:成功
获得 "agree count":成功感谢 numChildren()
得到 "percentage": 挑战,因为我需要他们的总和来计算这个。
关于如何实现这一点有什么想法吗?尝试使用一些回调技巧。不幸的是没有用。以下是我的愿景:
//javascript
var hash = "-dfd21DeH67";
var fbDB = new Firebase("https://<MyDB>.firebaseio.com/");
var buffer = [];
var sum;
fbDB.child(hash).once("value", function(opinion) {
var thisOpinion = opinion.val();
// First section
$.each(thisOpinion.options, function(i) {
fbPoll.child(hash + "/options/" + i + "/agrees").once("value", function(agrees) {
votes.push(agrees.numChildren());
sum += agrees.numChildren();
});
});
// execute only if the First section is done
// this is currently not the case, this gets executed before
// the first one finishes => result: #ResultsPanel stays empty
$.each(buffer, function(i) {
$("#ResultsPanel").append(
"<div class=\"OptionStatsBlock\">" +
"Option: " + thisOpinion.options[i].option + "<br>" +
"Total: " + buffer[i] + "<br>" +
"Percentage: " + ((buffer[i] / sum) * 100) +
"</div>"
);
});
});
提前致谢,
您可以使用 jQuery Promise 来处理调用的这种异步性质。
http://api.jquery.com/category/deferred-object/
甚至这个 post 也可能对您有所帮助 -
http://joseoncode.com/2011/09/26/a-walkthrough-jquery-deferred-and-promise/
对于其中一个,第二个 $.each 运行在空缓冲区数组上。所以它甚至不应该 运行。
更好的方法可能是向 "child_added" 事件添加事件侦听器,如下所示:从此处引用 https://www.firebase.com/docs/web/guide/retrieving-data.html#section-event-types
var ref = new Firebase("https://docs-examples.firebaseio.com/web/saving-data/fireblog/posts");
// Retrieve new posts as they are added to Firebase
ref.on("child_added", function(snapshot) {
var newPost = snapshot.val();
console.log("Author: " + newPost.author);
console.log("Title: " + newPost.title);
});
正如评论中所述:您似乎在与 Firebase(以及大多数现代网络)的异步特性作斗争。我鼓励您花尽可能多的时间来理解异步编程,以摆脱它目前造成的痛苦。它会让你在接下来的日子里远离更多的痛苦。
一种可能的解决方案
Firebase DataSnapshots 始终包含您请求的节点下的所有数据。因此,与其在循环中执行 once
(这几乎总是一个坏主意),您可以只请求更高一级的数据,然后循环并使用 child
:
// First section
$.each(thisOpinion.options, function(i) {
var agrees = opinion.child("/options/" + i + "/agrees");
votes.push(agrees.numChildren());
sum += agrees.numChildren();
});
此代码同步执行。
请注意,我没有对此进行测试,因此可能存在错别字。它基本上只是对您的代码稍作修改,使用 DataSnapshot.child
: https://www.firebase.com/docs/web/api/datasnapshot/child.html
我正在做一个项目,但无法让我的 javascript 按顺序工作。我知道 javascript 可以并行执行任务,因此当您向不响应的服务器发出请求时它不会卡住。这有它的优点和缺点。就我而言,这是一个痛苦的流浪汉。
场景如下,我使用 Firebase 来存储有多少人同意某个观点。这看起来如下:
我喜欢javascript
- 非常喜欢
- 我喜欢
- 喜欢或不喜欢它
- 不喜欢
- 我基本上讨厌它
人们现在可以 select 1 个选项。然后将他们的 selection 的记录放在选项下。结构:
-dfd21DeH67 : {
Title : "I like javascript"
options : {
0 : {
option : "I like it a lot"
agrees : {
-dfd21DQH6sq7 : "Jhon"
-dfd21DQH6sq8 : "Luke"
-dfd21DQH6sq9 : "Bruce"
}
}
1 : {
option : "I like it"
agrees : {
-dfd21DQH6sqA : "Harry"
-dfd21DQH6sqB : "Jimmy"
}
}
2 : {
option : "like nor dislike it"
agrees : {
-dfd21DQH6sqC : "Timmy"
-dfd21DQH6sqD : "Paul"
-dfd21DQH6sqE : "Danny"
-dfd21DQH6sqF : "Robin"
-dfd21DQH6sqG : "Dan"
}
}
3 : {
option : "don't like it"
agrees : {
-dfd21DQH6sqH : "Nathan"
-dfd21DQH6sqI : "Jerry"
}
}
4 : {
option : "I basically hate it"
agrees : {
-dfd21DQH6sqJ : "Tony"
}
}
}
}
现在,我想查询一下。我需要的每个选项的结果是:
- 选项(例如 "I like it a lot")
- 同意计数(例如 n 人同意这个)
- 百分比(例如,13 人中有 3 人说:"I like javascript"。这将是 ~23%)
现在,获取 "option" 并在浏览器中显示:成功
获得 "agree count":成功感谢 numChildren()
得到 "percentage": 挑战,因为我需要他们的总和来计算这个。
关于如何实现这一点有什么想法吗?尝试使用一些回调技巧。不幸的是没有用。以下是我的愿景:
//javascript
var hash = "-dfd21DeH67";
var fbDB = new Firebase("https://<MyDB>.firebaseio.com/");
var buffer = [];
var sum;
fbDB.child(hash).once("value", function(opinion) {
var thisOpinion = opinion.val();
// First section
$.each(thisOpinion.options, function(i) {
fbPoll.child(hash + "/options/" + i + "/agrees").once("value", function(agrees) {
votes.push(agrees.numChildren());
sum += agrees.numChildren();
});
});
// execute only if the First section is done
// this is currently not the case, this gets executed before
// the first one finishes => result: #ResultsPanel stays empty
$.each(buffer, function(i) {
$("#ResultsPanel").append(
"<div class=\"OptionStatsBlock\">" +
"Option: " + thisOpinion.options[i].option + "<br>" +
"Total: " + buffer[i] + "<br>" +
"Percentage: " + ((buffer[i] / sum) * 100) +
"</div>"
);
});
});
提前致谢,
您可以使用 jQuery Promise 来处理调用的这种异步性质。 http://api.jquery.com/category/deferred-object/
甚至这个 post 也可能对您有所帮助 - http://joseoncode.com/2011/09/26/a-walkthrough-jquery-deferred-and-promise/
对于其中一个,第二个 $.each 运行在空缓冲区数组上。所以它甚至不应该 运行。
更好的方法可能是向 "child_added" 事件添加事件侦听器,如下所示:从此处引用 https://www.firebase.com/docs/web/guide/retrieving-data.html#section-event-types
var ref = new Firebase("https://docs-examples.firebaseio.com/web/saving-data/fireblog/posts");
// Retrieve new posts as they are added to Firebase
ref.on("child_added", function(snapshot) {
var newPost = snapshot.val();
console.log("Author: " + newPost.author);
console.log("Title: " + newPost.title);
});
正如评论中所述:您似乎在与 Firebase(以及大多数现代网络)的异步特性作斗争。我鼓励您花尽可能多的时间来理解异步编程,以摆脱它目前造成的痛苦。它会让你在接下来的日子里远离更多的痛苦。
一种可能的解决方案
Firebase DataSnapshots 始终包含您请求的节点下的所有数据。因此,与其在循环中执行 once
(这几乎总是一个坏主意),您可以只请求更高一级的数据,然后循环并使用 child
:
// First section
$.each(thisOpinion.options, function(i) {
var agrees = opinion.child("/options/" + i + "/agrees");
votes.push(agrees.numChildren());
sum += agrees.numChildren();
});
此代码同步执行。
请注意,我没有对此进行测试,因此可能存在错别字。它基本上只是对您的代码稍作修改,使用 DataSnapshot.child
: https://www.firebase.com/docs/web/api/datasnapshot/child.html