可以缓存JSON以增加性能/加载时间



我正在使用一个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;
}

因此,让我们再深入研究一下上面的编码。简而言之,我们正在做的是:

  1. 打开错误报告并启动会话支持
  2. 检查我们是否已经为此用户读取了文件
  3. 如果是,请从存储中提取该值,并将其回显并退出。如果没有,请在下面继续
  4. 保存文件名并进行一些错误检查,以确保PHP能够找到、打开和读取文件的内容
  5. 读取文件内容
  6. 将解码后的json保存到您的"$_SESSION"变量中,由于传递给"json_decode"的参数为"true",json不是数组
  7. 将内容回显到屏幕

这将节省解析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有相同的机制:

  1. 在会话开始时,我生成一个随机字符串作为动态JavaScripts的会话密钥。此密钥以ASP.NET会话状态存储在密钥JsonSessionID下。这样我就可以在页面标记中引用它
  2. 我有一个"通用http处理程序"(一个ashx文件),当浏览器调用它时,它会返回一个包含JSON的.js文件
  3. 在我的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调用吗?你可以用页面直接传输数据

(当然,根据您的体系结构,您可以提出不同的解决方案)

最新更新