Google Timeline图表与Ajax/JSON请求绑定问题及解决方案咨询
Google Charts Timeline图表Ajax绑定问题排查与解决
一、初始实现(硬编码正常运行)
采用硬编码单条数据的方式可正常渲染Timeline图表,代码如下:
google.charts.load("current", { packages: ["timeline"] }); google.charts.setOnLoadCallback(drawChart); function drawChart() { var container = document.getElementById('CurrentOrders'); var chart = new google.visualization.Timeline(container); var data = new google.visualization.DataTable(); data.addColumn({ id: 'OrderNum', label: 'Order Number', type: 'string' }); data.addColumn({ id: 'PN', label: 'Part Number', type: 'string' }); data.addColumn({ id: 'StartDate', label: 'Start', type: 'date' }); data.addColumn({ id: 'EndDate', label: 'End', type: 'date' }); data.addRows([ ['M12345', 'MyPartNumber', new Date(2023, 1, 4), new Date(2023, 1, 6)] ]); var options = { timeline: { groupByRowLabel: true } }; chart.draw(data, options); }
二、WebMethod实现(数据返回符合预期)
通过WebMethod从数据库获取数据并序列化为JSON返回,返回结果格式正确:
<System.Web.Services.WebMethod> Public Shared Function GetOrders() As String Dim mOrder As List(Of Morder) = New List(Of Morder)() Dim constr As String = ConfigurationManager.ConnectionStrings("HYDMCS").ConnectionString Dim Query As String = "SELECT TOP(1) OrderNumber,Part_Number, CONVERT(DATE,GETDATE()) AS StartDate, CONVERT(DATE,DATEADD(DAY,2,GETDATE())) AS EndDate, MfgDueDate FROM HYD_GP_ProductionSchedule ORDER BY Part_Number DESC " Using con As New SqlConnection(constr) Try con.Open() Using sqlCmd As SqlCommand = New SqlCommand(Query, con) Using reader As SqlDataReader = sqlCmd.ExecuteReader While reader.Read If reader.HasRows Then mOrder.Add(New Morder() With { .OrderNum = reader(0).ToString(), .PN = reader(1).ToString(), .StartDate = reader(2), .EndDate = reader(3) }) End If End While End Using End Using con.Close() Catch ex As Exception If con.State = ConnectionState.Open Then con.Close() End If End Try End Using Dim js As JavaScriptSerializer = New JavaScriptSerializer() Return js.Serialize(mOrder) End Function
返回的JSON结果:
[{"OrderNum":"M531270 ","PN":"VXLD0500510 C ","StartDate":"/Date(1704344400000)/","EndDate":"/Date(1704517200000)/"}]
三、Ajax绑定问题(图表加载失败)
使用Ajax请求数据并绑定时出现错误,相关代码如下:
google.charts.load("current", { packages: ["timeline"] }); google.charts.setOnLoadCallback(drawChart); function drawChart() { $.ajax({ type: 'POST', dataType: 'JSON', contentType: 'application/json', url: 'PlannersWorkBench.aspx/GetOrders', success: function (response) { drawGraph(response.d); } }); }; function drawGraph(dataValues) { var data = new google.visualization.DataTable(); data.addColumn({ id: 'OrderNum', label: 'Order Number', type: 'string' }); data.addColumn({ id: 'PN', label: 'Part Number', type: 'string' }); data.addColumn({ id: 'StartDate', label: 'Start', type: 'date' }); data.addColumn({ id: 'EndDate', label: 'End', type: 'date' }); for (var i = 0; i < dataValues.length; i++) { data.addRow([dataValues[i].OrderNum, dataValues[i].PN, dataValues[i].StartDate, dataValues[i].EndDate]); // data.addRow(['M1', 'PN1', new Date(2023, 1, 4), new Date(2023, 1, 6)]); } var container = document.getElementById('CurrentOrders'); var chart = new google.visualization.Timeline(container); var options = { timeline: { groupByRowLabel: true } }; chart.draw(data, options); }
问题详情
- 直接使用返回数据绑定时,图表无法加载,仅显示错误;
- 排查时发现
dataValues.length为136(实际仅1条数据),循环后图表出现136行;硬编码数据虽能显示,但订单号不显示。
解决方案
核心问题分析
- 数据类型错误:WebMethod返回的是序列化后的JSON字符串,而非直接的JSON对象,导致
dataValues是字符串,length取的是字符串长度而非数组长度; - 日期格式不兼容:返回的日期格式为
/Date(时间戳)/,Google Charts Timeline需要JavaScript原生Date对象,无法直接识别该字符串格式; - 多余空格影响显示:返回的
OrderNum和PN包含多余空格,可能导致标签显示异常。
修改后的完整代码
google.charts.load("current", { packages: ["timeline"] }); google.charts.setOnLoadCallback(drawChart); function drawChart() { $.ajax({ type: 'POST', dataType: 'JSON', contentType: 'application/json', url: 'PlannersWorkBench.aspx/GetOrders', success: function (response) { // 解析JSON字符串为数组对象 var parsedData = JSON.parse(response.d); drawGraph(parsedData); }, error: function(xhr, status, error) { // 可选:添加错误处理 console.error('Ajax请求失败:', error); } }); }; function drawGraph(dataValues) { var data = new google.visualization.DataTable(); data.addColumn({ id: 'OrderNum', label: 'Order Number', type: 'string' }); data.addColumn({ id: 'PN', label: 'Part Number', type: 'string' }); data.addColumn({ id: 'StartDate', label: 'Start', type: 'date' }); data.addColumn({ id: 'EndDate', label: 'End', type: 'date' }); for (var i = 0; i < dataValues.length; i++) { // 处理日期格式:提取时间戳并转为Date对象 var startTimestamp = parseInt(dataValues[i].StartDate.replace('/Date(', '').replace(')/', '')); var endTimestamp = parseInt(dataValues[i].EndDate.replace('/Date(', '').replace(')/', '')); var startDate = new Date(startTimestamp); var endDate = new Date(endTimestamp); // 去除多余空格,优化显示 var orderNum = dataValues[i].OrderNum.trim(); var partNum = dataValues[i].PN.trim(); data.addRow([orderNum, partNum, startDate, endDate]); } var container = document.getElementById('CurrentOrders'); var chart = new google.visualization.Timeline(container); var options = { timeline: { groupByRowLabel: true } }; chart.draw(data, options); }
额外优化建议
- 在WebMethod中可以直接返回
List(Of Morder)而非序列化后的字符串,ASP.NET会自动处理JSON序列化,前端无需手动解析; - 可以在前端添加错误处理逻辑,便于排查请求失败问题;
- 若数据量较大,可考虑添加加载状态提示。
内容的提问来源于stack exchange,提问作者SoundWaves
相关产品推荐
相关产品推荐

