[英]How to Promise chain multiple google.charts.setOnLoadCallback's?
I am using Google's Firestore to obtain data and then using google.charts.setOnLoadCallback
to plot the data.我正在使用 Google 的 Firestore 获取数据,然后使用
google.charts.setOnLoadCallback
来 plot 数据。 The first drawing function draw1
calls for the data, and then the other draw2
and draw2
should reuse the same data.第一张图 function
draw1
调用数据,然后其他draw2
和draw2
应该重用相同的数据。
I tried Promise chaining the three google.charts.setOnLoadCallback
calls, in order to assure that the second and third calls get executed after the first in order to be sure I have the data passed through.我尝试 Promise 链接三个
google.charts.setOnLoadCallback
调用,以确保第二个和第三个调用在第一个调用之后执行,以确保我传递了数据。 The console logs should show 1, 2, 3, 4 as the order of execution, but instead, I get back 3, 4, 1, 2 - and the Step 3 and 4 have undefined data being passed to them - as the first two Promises have not finished running and the data does not exist yet.控制台日志应该显示 1、2、3、4 作为执行顺序,但相反,我返回 3、4、1、2 - 并且步骤 3 和 4 将未定义的数据传递给它们 - 作为前两个Promise 还没有运行完,数据还不存在。
Is it possible to daisy chain google.charts.setOnLoadCallback
Promises?是否可以菊花链
google.charts.setOnLoadCallback
Promises? See code example below:请参见下面的代码示例:
function initFirebase() {
// Initialize Cloud Firestore through Firebase
firebase.initializeApp({
apiKey: "MyKey",
authDomain: "MyDomain",
projectId: "MyProject",
});
return firebase.firestore();
}
const getFirebaseData = db => {
var doc_ref = db.collection('collection').doc('doc');
var queryLimit = doc_ref.orderBy("field1", "desc").limit(10);
var field1Arr = [];
var field2Arr = [];
return queryLimit.get()
.then(querySnapshot => {
querySnapshot.forEach(doc => {
var data = doc.data();
field1Arr.push(data.field1);
field2Arr.push(data.field2);
});
dataArr.push(field1Arr, field2Arr);
console.log("#1: Returning Data Array from Firebase", dataArr);
return dataArr;
});
}
function draw1() {
var db = initFirebase();
getFirebaseData(db).then(data => {
console.log("#2: Draw 1 Data: ", data);
return data;
});
}
function draw2(data) {
console.log("#3: Draw 2 Data: ", data);
return data;
}
function draw3(data) {
console.log("#4: Draw 3 data: ", data);
return data;
}
google.charts.load('current', {
packages: ['corechart', 'line']
});
google.charts.setOnLoadCallback(draw1)
.then(function(data) {
google.charts.setOnLoadCallback(draw2(data));
})
.then(function(data) {
google.charts.setOnLoadCallback(draw3(data));
});
The following are in my header:以下是我的header:
<script src="https://www.gstatic.com/charts/loader.js"></script>
<script src="https://www.gstatic.com/firebasejs/8.1.2/firebase-app.js"></script>
<script src="https://www.gstatic.com/firebasejs/8.1.2/firebase-firestore.js"></script>
Update更新
If I add return new Promise
to the draw functions then I am able to execute it in the right order, but the data is not passed from #3 to #4 now.如果我将
return new Promise
添加到绘制函数中,那么我就能够以正确的顺序执行它,但现在数据并未从#3 传递到#4。
function draw1() {
return new Promise (function (resolve,reject){
var db = initFirebase();
getFirebaseData(db).then(data => {
console.log("#2: Draw 1 Data: ", data);
resolve(data)
return data;
});
}
function draw2(data) {
return new Promise (function (resolve,reject){
console.log("#3: Draw 2 Data: ", data);
resolve(data);
return data;
});
}
function draw3(data) {
return new Promise (function (resolve,reject){
console.log("#4: Draw 3 Data: ", data);
resolve(data);
return data;
});
}
There's an error with your usage of setOnLoadCallback
.您对
setOnLoadCallback
的使用有误。 As mentioned here the purpose of setOnLoadCallback
is to call a function that will be executed once the libraries have been loaded, it's not required to use it every time you draw a graph, instead use the draw
method for creating the graph.正如这里提到的,
setOnLoadCallback
的目的是调用一个 function,一旦加载库就会执行,不需要每次绘制图形时都使用它,而是使用draw
方法创建图形。
My suggestion is to create a function that gathers all the data from Firestore, which will be called from the setOnLoadCallback
, and once the data has been gathered call the subsequent draw2, draw3 functions from there.我的建议是创建一个 function 来收集来自 Firestore 的所有数据,这将从
setOnLoadCallback
调用,一旦收集到数据,就会从那里调用后续的 draw2、draw3 函数。
A revamp of your code could be something like:修改您的代码可能是这样的:
google.charts.setOnLoadCallback(draw1);
function draw1() {
var db = initFirebase();
getFirebaseData(db).then(data => {
console.log("#2: Draw 1 Data: ", data);
let dataFromDB = modifyDataFromDB(data); //Here you should modify your data to use on the addRows method in the next two functions
draw2(data);
draw3(data);
});
}
function draw2(dataFromDB) {
//Create here your graph 2 with the data sent use the draw method
data = new google.visualization.DataTable();
data.addColumn('string', 'Column1');
data.addColumn('number', 'Column2');
data.addRows(dataFromDB); //I'm assuming here that the data from Firestore has already the format required
var options = {
'title': 'Graph Title',
'width': 400,
'height': 300
};
chart = new google.visualization.PieChart(document.getElementById('chart_div'));
google.visualization.events.addListener(chart, 'select', selectHandler);
chart.draw(data, options);
}
function draw3(dataFromDB){
//Create here your graph 3 with the data sent use the draw method
}
The code on the draw2
function is just an example of how it would look a function that creates a graph so you can understand a little bit better what goes there. draw2
function 上的代码只是创建图形的 function 的外观示例,因此您可以更好地理解其中的内容。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.