我正在使用一个JSON文件来自动填充下拉列表。它并不庞大(3000行,而且还在增长),但刷新页面所花费的时间变得非常明显。
第一次加载页面时,读取JSON,这取决于用户选择的选项决定了JSON的哪一部分用于填充下拉列表。
之后,每次刷新或菜单选择时都会加载它。是否可以以某种方式缓存这些值,以防止需要一次又一次地重新加载?
谢谢。
编辑:更多信息:它本质上是一个单元转换器。JSON包含所有细节。例如,当用户选择"Temp"时,会进行调用并填充列表。转换完成后,您可以花一整天的时间运行临时转换,它们会很好,但每次用户更改转换类型(现在为长度)时,页面都会刷新,并花费大量时间。
不幸的是,我不知道PHP中有标准化的全局缓存机制。本文介绍了Optimizer Plus,一个第三方加速器,从5.5版本开始就包含在核心PHP中。不确定你使用的是什么版本,但你可以试试。
另一方面,您是否考虑过andrew所指出的文件存储?我认为在这种情况下,它与$_SESSION
相结合确实可以帮助您。让我给您举一个使用现有JSON数据的示例:
服务器端
将JSON数据存储在PHP服务器上的.json
文件中:
{
"data": "some data",
"data2": "more data",
"data3": [
...
],
etc.
}
注意:请确保正确格式化JSON数据。请记住,所有字符串都必须用双引号"
括起来。
在PHP中,使用if语句来决定适当的操作:
error_reporting(E_ALL);
ini_set("display_errors", "On");
session_start();
if(isset($_SESSION['dataCache'])) {
echo json_encode($_SESSION['dataCache']);
} else {
$file = 'data.json';
if (!is_file($file) || !is_readable($file)) {
die("File not accessible.");
}
$contents = file_get_contents($file);
$_SESSION['dataCache'] = json_decode($contents, true);
echo $contents;
}
因此,让我们再深入研究一下上面的编码。简而言之,我们正在做的是:
- 打开错误报告并启动会话支持
- 检查我们是否已经为此用户读取了文件
- 如果是,请从存储中提取该值,并将其回显并退出。如果没有,请在下面继续
- 保存文件名并进行一些错误检查,以确保PHP能够找到、打开和读取文件的内容
- 读取文件内容
- 将解码后的json保存到您的"$_SESSION"变量中,由于传递给"json_decode"的参数为"true",json不是数组
- 将内容回显到屏幕
这将节省解析JSON数据和/或在服务器上手动构建JSON数据的时间和麻烦。它将为用户session
缓存,以便他们可以使用它。
客户端
我想你是在用ajax
来获取信息?如果没有纠正我的错误,但我认为这就是你的一些JavaScript发挥作用的地方。如果是这样,您可以考虑:
从服务器返回数据时,将返回的数据存储在用户浏览器上的sessionStorage
中:
$.ajax({
...
success: function (res) {
localStorage.setItem("dataCache", JSON.stringify(res));
},
...
});
或者,如果您使用promise对象:
$.ajax({
...
}).done(function (res) {
localStorage.setItem("dataCache", JSON.stringify(res));
});
当你需要阅读它时,你可以做一个简单的测试:
var data;
// This returns null if the item is not in local storage.
// Since JavaScript is truthy falsy, it will be evaluated as false.
if(localStorage.getItem("dataCache")) {
data = JSON.parse(localStorage.getItem("dataCache"));
} else {
// Make ajax call, fetch object and store in localStorage in the success or done callbacks as described above
}
注意:
localStorage
是HTML5中的一个新功能,因此它还没有在所有浏览器上得到完全支持。然而,大多数主要的都是这样,甚至可以追溯到IE8(我认为)。然而,对于每个网站需要容纳多少浏览器,并没有标准化的大小限制。
考虑到这一点很重要。我可以保证,您可能无法将整个30000行字符串存储在localStorage中。但是,您可以将此作为一个开始。与服务器端解决方案相结合,您应该可以看到性能的提高。
希望这能有所帮助。
我使用浏览器的缓存来确保我的大块JSON在每个会话中只下载一次。我在ASP.NET中编程,但我确信PHP有相同的机制:
- 在会话开始时,我生成一个随机字符串作为动态JavaScripts的会话密钥。此密钥以ASP.NET会话状态存储在密钥
JsonSessionID
下。这样我就可以在页面标记中引用它 - 我有一个"通用http处理程序"(一个ashx文件),当浏览器调用它时,它会返回一个包含JSON的.js文件
- 在我的HTML中,我包含了动态脚本:
<script type="text/javascript" src="/dynamicJSON.ashx?v=<%= JsonSessionID %>"></script>
浏览器将自动缓存作为脚本包含的任何URL。下次浏览器被要求从URL加载缓存脚本时,它只会从本地磁盘加载文件。这包括像这样的动态页面。
通过在其中添加?v=
,我确保JSON在每个会话中更新一次。
编辑
我刚刚意识到您的JSON可能是静态的。如果是这样的话,您可以将JSON放入HTML中包含的静态.js文件中,浏览器会缓存它。
// conversionData.js
var conversionData = { "a":1,"b":2,"c":3 };
当您包含conversionData.js时,conversionData变量将与动态更新下拉列表的页面的其余JavaScript一起在作用域中。
编辑2
如果你提供的是静态文件,这篇博客文章有一个很好的模式,可以根据文件的日期修改属性来破坏缓存。即,仅当文件在服务器上被改变时才下载该文件。
我还没有找到一个好的方法来破坏通过数据库查找表创建的JSON缓存,而不是每个会话。这并不理想,因为数据库可能会在会话中期更改。
一旦您将JSON数据解码为对象,您就可以保留该对象,它应该至少持续到页面重新加载。
如果你想在重新加载之间坚持,你可能想看看HTML5的localStorage
等
你需要制定一个年龄策略,也许也可以把当前日期放在里面,这样你就可以根据需要进行比较并过期。
我建议将json数据存储到会话中。在第一次页面加载时,您可以编写一个脚本来获取json数据,然后将它们存储到会话中。在每次页面加载/刷新之后,您可以检查我们的会话来决定要做什么——使用会话数据或再次获取json数据。
这种方法适用于小规模数据(例如:一系列产品-颜色-尺寸-价格)。
根据您的数据,您应该测试加载时间。
这里有一个简单的破解方法:
使用参数"bla-bla.html"创建对php文件的调用作为GET请求或者"blabla.css"…你知道,它让浏览器认为它不是php,而是"html"或"css"。浏览器会缓存它。
要验证这个技巧是否有效,请转到浏览器开发面板的"网络"选项卡,你会看到"type"列和"transfered"列,而不是php和实际大小,你会发现"html"one_answers"(缓存)"
当您将"blah-blak.html"之类的参数传递到php文件并期望它不会被缓存时,也可以知道这一点。好吧,它将被缓存。
在FireFox Quantum 57.0.1(Mac 64位)上测试
p.S.
在这种情况下,Mac上的Chrome 63能够识别真实的文件类型。所以它不能被愚弄。
跳出框框思考:
但如果你的列表有3000行并且还在增长(正如你所说)你能确定它的最大尺寸吗?
假设答案是10000(最多)项;那么你真的需要ajax调用吗?你可以用页面直接传输数据
(当然,根据您的体系结构,您可以提出不同的解决方案)