javascript - 在 Google Apps 脚本中使用 sessionStorage - 未捕获的类型错误:未定义
问题描述
我有一个网页(用 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。我收到一个“未定义”错误,我无法追踪。
使用 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 中则显示数据,事情似乎按我的意愿工作。
推荐阅读
- swiftui - 线程 1:致命错误:没有 ObservableObject 类型
- ansible - Ansible 循环遍历从 dict 中提取的列表
- netezza - Netezza 从外部文件导入错误:不支持的外部表引用,无法导出形状
- terraform - aws_lambda_event_source_mapping 上的 ValidationException
- javascript - Angular/JS/Typescript- 递归访问对象中的属性
- pine-script - 无法关闭策略
- python - /quizmaker/ 处的 IntegrityError(1048,“列 'id_id' 不能为空”)
- css - React 组件从上一页获取 css
- java - 在 Java 中快速比较大数据集中的值和小数据集中的值
- junit - 在单个自动化测试中评估多个测试用例的技术?