Using sessionStorage in Google Apps Script - Uncaught Type Error: undefined
Using sessionStorage in Google Apps Script - Uncaught Type Error: undefined
我有一个网页(使用 Google Apps 脚本编写)在初始加载时调用服务器,首先获取一组下拉选项以创建过滤器,然后再次调用以初始化时间线图表。我已经拥有这个页面很长时间了,它按预期工作。
我现在正在做的是将一些数据保存到 sessionStorage,这样它就不必每次都调用服务器,以防用户离开页面。这是我第一次尝试这样做,所以我还在学习中。
我的第一步是保存下拉项。一旦我让它工作,我会尝试对图表数据做同样的事情。
我留下了一些原始代码,但注释掉了。
$(function() {
//google.script.run.withSuccessHandler(buildDropDowns).buildDropDowns();
//google.script.run.withSuccessHandler(getChartData).getChartData("-", "-", "-", "-", "-", "-", "-");
testSession();
});
function testSession() {
if(sessionStorage.getItem("drop") == null) {
google.script.run.withSuccessHandler(buildDropDowns).buildDropDowns();
} else {
buildDropDowns(sessionStorage.getItem("drop"));
}
if(sessionStorage.getItem("chart") == null) {
google.script.run.withSuccessHandler(getChartData).getChartData("-", "-", "-", "-", "-", "-", "-");
} else {
getChartData(sessionStorage.getItem("chart"));
}
}
function buildDropDowns(JSONObj) {
sessionStorage.setItem("drop", JSONObj);
var dropDownObj = JSON.parse(JSONObj);
// do a bunch of things with the dropDownObj
}
function getChartData(JSONObj) {
sessionStorage.setItem("chart", JSONObj);
var dataObj = JSON.parse(JSONObj);
var rawChartData = dataObj.chartData;
var count = dataObj.count;
var colors = dataObj.colors;
const dateIndices = [3,4];
const chartData = rawChartData.map(function (row) {
return row.map(function (col, index) {
return (dateIndices.indexOf(index) === -1) ? col : new Date(col);
});
});
if(chartData.length == 1) {
document.getElementById("chartDiv").innerHTML = "<b>No projects meet your criteria</b>";
} else {
buildChart(chartData, count, colors);
}
}
google.charts.load('current', {'packages':['timeline']});
function buildChart(chartData, count, colors) {
var container = document.getElementById('chartDiv');
//*** EDIT - THIS APPEARS TO BE PROBLEM LINE ***
var chart = new google.visualization.Timeline(container);
//Is there something about visualizations that are different on a reload?
var dataTable = new google.visualization.DataTable();
dataTable.addColumn({ type: 'string', id: 'Project' });
dataTable.addColumn({ type: 'string', id: 'dummy bar label' });
dataTable.addColumn({ type: 'string', role: 'tooltip', p: {'html':true}});
dataTable.addColumn({ type: 'date', id: 'Start' });
dataTable.addColumn({ type: 'date', id: 'End' });
dataTable.addColumn({ type: 'number', id: 'sortValue' });
dataTable.addColumn({ type: 'string', id: 'gate' });
dataTable.addRows(chartData);
var options = {
height: Math.min(800, (chartData.length*45)+60),
width:"100%",
};
var view = new google.visualization.DataView(dataTable);
view.setColumns([0, 1, 2, 3, 4]); // exclude column 5 (sequence)
chart.draw(view, options);
}
下拉部分确实符合我的预期。第一次打开页面,调用服务器获取数据,将JSONObj保存到sessionStorage中。当刷新页面或导航离开然后再返回时,我可以看到它不是去服务器获取那些下拉项,而是从 sessionStorage 获取 JSONObj,并正确处理它。成功!!
所以我对图表数据进行了同样的尝试。同样,当它第一次加载页面时,它会去服务器获取数据,并将 JSONObj 保存到 sessionStorage。但是当我刷新选项卡(或导航离开和返回)时,它无法正确处理来自 sessionStorage 的 JSONObj。我收到一个 'undefined' 错误,我无法找到它。
使用 console.log(),看起来 JSONObj 最初从服务器发送时与从 sessionData 检索时相同。但很明显,它有一些其他代码不喜欢的地方。它正确处理原件,但在 sessionData 副本上出错。
这只是我遗漏的一些愚蠢的东西吗(同样,这是我第一次尝试使用 sessionData 做事)?或者 sessionData 存储 JSONObj 的方式是否以某种方式改变了它,以便在检索时不能以相同的方式处理它?为什么它适用于 dropDown 进程,而不适用于 chartData 进程?
如有任何正确方向的建议,我们将不胜感激。
感谢@RonM 为我指明了正确的方向。我现在了解到的是,以前,可视化包有时间加载,同时调用服务器来捕获数据。一旦我将服务器从后续加载的流程中移出,数据就会在时间线有机会完成加载之前尝试写入时间线。
我已基于此对代码进行了一些更新,以确保图表包在尝试处理来自 sessionData 的数据之前加载。
$(function() {
//google.script.run.withSuccessHandler(buildDropDowns).buildDropDowns();
//google.script.run.withSuccessHandler(getChartData).getChartData("-", "-", "-", "-", "-", "-", "-");
//testSession(); //COMMENT OUT NOW
google.charts.load('current', {'packages':['timeline'], callback: testSession }); // ADDED IN ITS PLACE
});
function testSession() {
if(sessionStorage.getItem("drop") == null) {
google.script.run.withSuccessHandler(buildDropDowns).buildDropDowns();
} else {
buildDropDowns(sessionStorage.getItem("drop"));
}
if(sessionStorage.getItem("chart") == null) {
google.script.run.withSuccessHandler(getChartData).getChartData("-", "-", "-", "-", "-", "-", "-");
} else {
getChartData(sessionStorage.getItem("chart"));
}
}
function buildDropDowns(JSONObj) {
sessionStorage.setItem("drop", JSONObj);
var dropDownObj = JSON.parse(JSONObj);
// do a bunch of things with the dropDownObj
}
function getChartData(JSONObj) {
sessionStorage.setItem("chart", JSONObj);
var dataObj = JSON.parse(JSONObj);
var rawChartData = dataObj.chartData;
var count = dataObj.count;
var colors = dataObj.colors;
const dateIndices = [3,4];
const chartData = rawChartData.map(function (row) {
return row.map(function (col, index) {
return (dateIndices.indexOf(index) === -1) ? col : new Date(col);
});
});
if(chartData.length == 1) {
document.getElementById("chartDiv").innerHTML = "<b>No projects meet your criteria</b>";
} else {
buildChart(chartData, count, colors);
}
}
//google.charts.load('current', {'packages':['timeline']}); //COMMENT OUT NOW
function buildChart(chartData, count, colors) {
var container = document.getElementById('chartDiv');
//*** EDIT - THIS APPEARS TO BE PROBLEM LINE ***
var chart = new google.visualization.Timeline(container);
//Is there something about visualizations that are different on a reload?
var dataTable = new google.visualization.DataTable();
dataTable.addColumn({ type: 'string', id: 'Project' });
dataTable.addColumn({ type: 'string', id: 'dummy bar label' });
dataTable.addColumn({ type: 'string', role: 'tooltip', p: {'html':true}});
dataTable.addColumn({ type: 'date', id: 'Start' });
dataTable.addColumn({ type: 'date', id: 'End' });
dataTable.addColumn({ type: 'number', id: 'sortValue' });
dataTable.addColumn({ type: 'string', id: 'gate' });
dataTable.addRows(chartData);
var options = {
height: Math.min(800, (chartData.length*45)+60),
width:"100%",
};
var view = new google.visualization.DataView(dataTable);
view.setColumns([0, 1, 2, 3, 4]); // exclude column 5 (sequence)
chart.draw(view, options);
}
现在我在页面加载时加载可视化包,然后才在需要时调用服务器以获取数据,或者如果数据已经在 sessionData 中则显示数据,一切似乎都在按我想要的方式进行到.
我有一个网页(使用 Google Apps 脚本编写)在初始加载时调用服务器,首先获取一组下拉选项以创建过滤器,然后再次调用以初始化时间线图表。我已经拥有这个页面很长时间了,它按预期工作。
我现在正在做的是将一些数据保存到 sessionStorage,这样它就不必每次都调用服务器,以防用户离开页面。这是我第一次尝试这样做,所以我还在学习中。
我的第一步是保存下拉项。一旦我让它工作,我会尝试对图表数据做同样的事情。
我留下了一些原始代码,但注释掉了。
$(function() {
//google.script.run.withSuccessHandler(buildDropDowns).buildDropDowns();
//google.script.run.withSuccessHandler(getChartData).getChartData("-", "-", "-", "-", "-", "-", "-");
testSession();
});
function testSession() {
if(sessionStorage.getItem("drop") == null) {
google.script.run.withSuccessHandler(buildDropDowns).buildDropDowns();
} else {
buildDropDowns(sessionStorage.getItem("drop"));
}
if(sessionStorage.getItem("chart") == null) {
google.script.run.withSuccessHandler(getChartData).getChartData("-", "-", "-", "-", "-", "-", "-");
} else {
getChartData(sessionStorage.getItem("chart"));
}
}
function buildDropDowns(JSONObj) {
sessionStorage.setItem("drop", JSONObj);
var dropDownObj = JSON.parse(JSONObj);
// do a bunch of things with the dropDownObj
}
function getChartData(JSONObj) {
sessionStorage.setItem("chart", JSONObj);
var dataObj = JSON.parse(JSONObj);
var rawChartData = dataObj.chartData;
var count = dataObj.count;
var colors = dataObj.colors;
const dateIndices = [3,4];
const chartData = rawChartData.map(function (row) {
return row.map(function (col, index) {
return (dateIndices.indexOf(index) === -1) ? col : new Date(col);
});
});
if(chartData.length == 1) {
document.getElementById("chartDiv").innerHTML = "<b>No projects meet your criteria</b>";
} else {
buildChart(chartData, count, colors);
}
}
google.charts.load('current', {'packages':['timeline']});
function buildChart(chartData, count, colors) {
var container = document.getElementById('chartDiv');
//*** EDIT - THIS APPEARS TO BE PROBLEM LINE ***
var chart = new google.visualization.Timeline(container);
//Is there something about visualizations that are different on a reload?
var dataTable = new google.visualization.DataTable();
dataTable.addColumn({ type: 'string', id: 'Project' });
dataTable.addColumn({ type: 'string', id: 'dummy bar label' });
dataTable.addColumn({ type: 'string', role: 'tooltip', p: {'html':true}});
dataTable.addColumn({ type: 'date', id: 'Start' });
dataTable.addColumn({ type: 'date', id: 'End' });
dataTable.addColumn({ type: 'number', id: 'sortValue' });
dataTable.addColumn({ type: 'string', id: 'gate' });
dataTable.addRows(chartData);
var options = {
height: Math.min(800, (chartData.length*45)+60),
width:"100%",
};
var view = new google.visualization.DataView(dataTable);
view.setColumns([0, 1, 2, 3, 4]); // exclude column 5 (sequence)
chart.draw(view, options);
}
下拉部分确实符合我的预期。第一次打开页面,调用服务器获取数据,将JSONObj保存到sessionStorage中。当刷新页面或导航离开然后再返回时,我可以看到它不是去服务器获取那些下拉项,而是从 sessionStorage 获取 JSONObj,并正确处理它。成功!!
所以我对图表数据进行了同样的尝试。同样,当它第一次加载页面时,它会去服务器获取数据,并将 JSONObj 保存到 sessionStorage。但是当我刷新选项卡(或导航离开和返回)时,它无法正确处理来自 sessionStorage 的 JSONObj。我收到一个 'undefined' 错误,我无法找到它。
使用 console.log(),看起来 JSONObj 最初从服务器发送时与从 sessionData 检索时相同。但很明显,它有一些其他代码不喜欢的地方。它正确处理原件,但在 sessionData 副本上出错。
这只是我遗漏的一些愚蠢的东西吗(同样,这是我第一次尝试使用 sessionData 做事)?或者 sessionData 存储 JSONObj 的方式是否以某种方式改变了它,以便在检索时不能以相同的方式处理它?为什么它适用于 dropDown 进程,而不适用于 chartData 进程?
如有任何正确方向的建议,我们将不胜感激。
感谢@RonM 为我指明了正确的方向。我现在了解到的是,以前,可视化包有时间加载,同时调用服务器来捕获数据。一旦我将服务器从后续加载的流程中移出,数据就会在时间线有机会完成加载之前尝试写入时间线。
我已基于此对代码进行了一些更新,以确保图表包在尝试处理来自 sessionData 的数据之前加载。
$(function() {
//google.script.run.withSuccessHandler(buildDropDowns).buildDropDowns();
//google.script.run.withSuccessHandler(getChartData).getChartData("-", "-", "-", "-", "-", "-", "-");
//testSession(); //COMMENT OUT NOW
google.charts.load('current', {'packages':['timeline'], callback: testSession }); // ADDED IN ITS PLACE
});
function testSession() {
if(sessionStorage.getItem("drop") == null) {
google.script.run.withSuccessHandler(buildDropDowns).buildDropDowns();
} else {
buildDropDowns(sessionStorage.getItem("drop"));
}
if(sessionStorage.getItem("chart") == null) {
google.script.run.withSuccessHandler(getChartData).getChartData("-", "-", "-", "-", "-", "-", "-");
} else {
getChartData(sessionStorage.getItem("chart"));
}
}
function buildDropDowns(JSONObj) {
sessionStorage.setItem("drop", JSONObj);
var dropDownObj = JSON.parse(JSONObj);
// do a bunch of things with the dropDownObj
}
function getChartData(JSONObj) {
sessionStorage.setItem("chart", JSONObj);
var dataObj = JSON.parse(JSONObj);
var rawChartData = dataObj.chartData;
var count = dataObj.count;
var colors = dataObj.colors;
const dateIndices = [3,4];
const chartData = rawChartData.map(function (row) {
return row.map(function (col, index) {
return (dateIndices.indexOf(index) === -1) ? col : new Date(col);
});
});
if(chartData.length == 1) {
document.getElementById("chartDiv").innerHTML = "<b>No projects meet your criteria</b>";
} else {
buildChart(chartData, count, colors);
}
}
//google.charts.load('current', {'packages':['timeline']}); //COMMENT OUT NOW
function buildChart(chartData, count, colors) {
var container = document.getElementById('chartDiv');
//*** EDIT - THIS APPEARS TO BE PROBLEM LINE ***
var chart = new google.visualization.Timeline(container);
//Is there something about visualizations that are different on a reload?
var dataTable = new google.visualization.DataTable();
dataTable.addColumn({ type: 'string', id: 'Project' });
dataTable.addColumn({ type: 'string', id: 'dummy bar label' });
dataTable.addColumn({ type: 'string', role: 'tooltip', p: {'html':true}});
dataTable.addColumn({ type: 'date', id: 'Start' });
dataTable.addColumn({ type: 'date', id: 'End' });
dataTable.addColumn({ type: 'number', id: 'sortValue' });
dataTable.addColumn({ type: 'string', id: 'gate' });
dataTable.addRows(chartData);
var options = {
height: Math.min(800, (chartData.length*45)+60),
width:"100%",
};
var view = new google.visualization.DataView(dataTable);
view.setColumns([0, 1, 2, 3, 4]); // exclude column 5 (sequence)
chart.draw(view, options);
}
现在我在页面加载时加载可视化包,然后才在需要时调用服务器以获取数据,或者如果数据已经在 sessionData 中则显示数据,一切似乎都在按我想要的方式进行到.