可以缓存 JSON 以提高性能/加载时间吗?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/17612962/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-03 19:57:00  来源:igfitidea点击:

Possible to cache JSON to increase performance / load time?

javascriptjson

提问by null

I'm using a JSON file to autopopulate a drop down list. It's by no means massive (3000 lines and growing) but the time taken to refresh the page is becoming very noticeable.

我正在使用 JSON 文件自动填充下拉列表。它绝不是庞大的(3000 行并且还在增长),但是刷新页面所花费的时间变得非常明显。

The first time the page is loaded the JSON is read, depending on what option the user has selected dictates which part of the JSON is used to populate the drop down.

第一次加载页面时,会读取 JSON,具体取决于用户选择的选项决定了 JSON 的哪一部分用于填充下拉列表。

It's then loaded on every refresh or menu selection after. Is it possible to somehow cache the values to prevent the need for it to be reloaded time and time again?

然后在每次刷新或菜单选择后加载它。是否有可能以某种方式缓存值以防止需要一次又一次地重新加载它?

Thanks.

谢谢。

EDIT: More Info: It's essentially a unit converter. The JSON holds all the details. When a users selects 'Temp' for example a call is made and the lists are populated. Once a conversion is complete you can spend all day running temp conversions and they'll be fine but everytime a user changes conversion type so now length, the page refreshes and takes a noticeable amount of time.

编辑:更多信息:它本质上是一个单位转换器。JSON 包含所有详细信息。例如,当用户选择“Temp”时,会进行呼叫并填充列表。转换完成后,您可以花一整天时间运行临时转换,它们会很好,但每次用户更改转换类型时,页面都会刷新并花费大量时间。

回答by War10ck

Unfortunately, I don't know of a standardized global caching mechanism in PHP. Thisarticle says that Optimizer Plus, a third party accelerator, is being included in core PHP starting in version 5.5. Not sure what version you are using but you could try that.

不幸的是,我不知道 PHP 中的标准化全局缓存机制。文章说,被包含在PHP核心的5.5版本开始优化升级,第三方加速器。不确定您使用的是哪个版本,但您可以尝试一下。

On a different note, have you considered file storage as andrewpointed out? I think it combined with $_SESSIONcould really help you in this case. Let me give you an example that would work with your existing JSON data:

另一方面,您是否考虑过安德鲁指出的文件存储?我认为$_SESSION在这种情况下,它结合起来真的可以帮助你。让我举一个可以处理现有 JSON 数据的示例:

Server Side

服务器端

Store your JSON data in a .jsonfile on your PHP server:

将 JSON 数据存储在.jsonPHP 服务器上的文件中:

{
    "data": "some data",
    "data2": "more data",
    "data3": [
        ...
     ],
     etc.
}

Note:Make sure to properly format your JSON data. Remember all strings must be enclosed in doublequotes ".

注意:确保正确格式化您的 JSON 数据。请记住,所有字符串都必须用引号括起来"

In PHP, use an if statement to decide the appropriate action:

在 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;
}

So lets dig into the above coding a little more. So here's what we are doing in a nutshell:

所以让我们深入研究一下上面的编码。简而言之,这就是我们正在做的事情:

  1. Turn on error reporting and start session support.
  2. Check to see if we've already read the file for this user.
  3. If so, pull the value from storage and echo it out and exit. If not continue below.
  4. Save off the file name and do a little error checking to ensure PHP can find, open and read the contents of the file.
  5. Read the file contents.
  6. Save the decoded json, which is not an array because of the `true` parameter passed to `json_decode`, into your `$_SESSION` variable.
  7. Echo the contents to the screen.
  1. 打开错误报告并启动会话支持。
  2. 检查我们是否已经读取了该用户的文件。
  3. 如果是,则从存储中提取值并将其回显并退出。如果没有继续下面。
  4. 保存文件名并做一些错误检查以确保 PHP 可以找到、打开和读取文件的内容。
  5. 读取文件内容。
  6. 将解码后的 json(由于传递给 `json_decode` 的 `true` 参数不是数组)保存到你的 `$_SESSION` 变量中。
  7. 将内容回显到屏幕上。

This will save you the time and hazzle of parsing out JSON data and/or building it manually on the server. It will be cached for the users sessionso that they can use it through out.

这将为您节省解析 JSON 数据和/或在服务器上手动构建它的时间和麻烦。它将为用户缓存,session以便他们可以一直使用它。

Client Side

客户端

I assume you are using ajaxto fetch the information? If not correct me, but I was assuming that's where some of your JavaScript comes into play. If so you may consider this:

我假设您正在使用ajax来获取信息?如果不纠正我,但我假设这就是您的一些 JavaScript 发挥作用的地方。如果是这样,您可以考虑:

Store the returned data in sessionStorageon the user's browser when it's returned from the server:

sessionStorage当它从服务器返回时,将返回的数据存储在用户的浏览器中:

$.ajax({
    ...
    success: function (res) {
        localStorage.setItem("dataCache", JSON.stringify(res));
    },
    ...
});

Or if you use promise objects:

或者,如果您使用承诺对象:

$.ajax({
    ...
}).done(function (res) {
    localStorage.setItem("dataCache", JSON.stringify(res));
});

When you need to read it you can do a simple test:

当你需要阅读它时,你可以做一个简单的测试:

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
}

Notes:

笔记:

localStorageis a new feature in HTML5, so it's not fully supported on all browsers yet. Most of the major ones do however, even as far back as IE8 (I think). However, there is no standardized size limit on how much these browsers are required to hold per site.

localStorage是 HTML5 中的一项新功能,因此尚未在所有浏览器上完全支持。然而,大多数主要的都可以,甚至可以追溯到 IE8(我认为)。但是,对于每个站点需要多少这些浏览器,没有标准化的大小限制。

It's important to take that into consideration. I can guarantee you probably will not be able to store the entire 30,000 line string in localStorage. However, you could use this as a start. Combined with the server side solution, you should see a performance increase.

考虑到这一点很重要。我可以保证您可能无法将整个 30,000 行字符串存储在 localStorage 中。但是,您可以以此为起点。结合服务器端解决方案,您应该会看到性能提升。

Hope this helps.

希望这可以帮助。

回答by Walter Stabosz

I use the browser's cacheto ensure that my large chunk of JSON is only downloaded once per session. I program in ASP.NET, but I'm sure PHP has the same mechanisms:

我使用浏览器的缓存来确保每个会话只下载一次我的大块 JSON。我在 ASP.NET 中编程,但我确信 PHP 具有相同的机制:

  1. On session start, I generate a random string as session key for my dynamic JavaScripts. This key get stored in the ASP.NET session stateunder the key JsonSessionID. That way I can refer to it in my page markup.
  2. I have a "generic http handler" (an ashx file)that when called by the browser, returns a .js file containing my JSON.
  3. In my HTML I include the dynamic script: <script type="text/javascript" src="/dynamicJSON.ashx?v=<%= JsonSessionID %>"></script>
  1. 在会话开始时,我生成一个随机字符串作为动态 JavaScript 的会话密钥。这个键被存储在键下的ASP.NET 会话状态中JsonSessionID。这样我就可以在我的页面标记中引用它。
  2. 我有一个“通用 http 处理程序” (一个 ashx 文件),当浏览器调用它时,会返回一个包含我的 JSON 的 .js 文件。
  3. 在我的 HTML 中,我包含了动态脚本: <script type="text/javascript" src="/dynamicJSON.ashx?v=<%= JsonSessionID %>"></script>

The browser will automatically cache any URLs included as scripts. The next time the browser is asked to load a cached script from a URL, it will just load up the file from the local disk. This includes dynamic pages like this.

浏览器将自动缓存作为脚本包含的任何 URL。下次要求浏览器从 URL 加载缓存脚本时,它只会从本地磁盘加载文件。这包括像这样的动态页面。

By adding the ?v=in there, I ensure that the JSON is updated once per session.

通过?v=在那里添加,我确保每个 session 更新一次 JSON

Edit

编辑

I just realized that your JSON is probably static. If that's the case, you can just put your JSON into a static .js file that you include in your HTML, and the browser will cache it.

我刚刚意识到您的 JSON 可能是静态的。如果是这种情况,您只需将 JSON 放入包含在 HTML 中的静态 .js 文件,浏览器就会缓存它。

// conversionData.js
var conversionData = { "a":1,"b":2,"c":3 };

When you include the conversionData.js, the conversionData variable will be in scope with the rest of your page's JavaScript that dynamically updates the drop-downs.

当您包含conversionData.js 时,conversionData 变量将与动态更新下拉列表的页面的其余JavaScript 一起在范围内。

Edit 2

编辑 2

If you are serving static files, this blog posthas a good pattern for cache-busting based on the file's date modified property. i.e. the file is only downloaded when it is changed on the server.

如果您正在提供静态文件,这篇博客文章有一个基于文件的修改日期属性的缓存破坏模式。即文件仅在服务器上更改时才下载。

I have yet to find a good method for cache-busting JSON created via database lookup tables, other than per-session. Which isn't ideal because the database could change mid-session.

除了每个会话之外,我还没有找到通过数据库查找表创建的缓存破坏 JSON 的好方法。这并不理想,因为数据库可能会在会话期间更改。

回答by Yevgeniy Afanasyev

Here is a simple hack:

这是一个简单的黑客:

Create a call to a php file as GET request with parameter "bla-bla.html" or "bla-bla.css"... well you know, it makes browser think it is not a php, but rather "html" or "css". And browser will cache it.

使用参数“bla-bla.html”或“bla-bla.css”创建对 php 文件的调用作为 GET 请求......好吧,您知道,它使浏览器认为它不是 php,而是“html”或“CSS”。浏览器会缓存它。

To verify that the trick is working - go to the "network" tab of the browser dev panel and you will see column "type" there along with "transferred" - instead of having php there and actual size, you will find "html" and "(cached)"

要验证该技巧是否有效 - 转到浏览器开发面板的“网络”选项卡,您将在那里看到“类型”和“已转移”列 - 而不是在那里有 php 和实际大小,您会发现“html”和“(缓存)”

This is also good to know when you passing parameters like "blah-blak.html" to the php file and expect it will not be cached. Well, it will be cached.

当您将诸如“blah-blak.html”之类的参数传递给 php 文件并期望它不会被缓存时,了解这一点也很有好处。嗯,它会被缓存。

Tested on FireFox Quantum 57.0.1 (Mac 64bit)

在 FireFox Quantum 57.0.1(Mac 64 位)上测试

P.S.

聚苯乙烯

Chrome 63 on Mac is capable of recognising real file type in this situation. So it cannot be fooled.

在这种情况下,Mac 上的 Chrome 63 能够识别真实的文件类型。所以它不能被愚弄。

回答by Lloyd

Once you've got your JSON data decoded into an object you can just keep the object around, it should persist until a page reload at least.

一旦您将 JSON 数据解码为一个对象,您就可以保留该对象,它至少应该持续到页面重新加载。

If you want to persist between reloads you might want to look at HTML5's localStorageetc.

如果您想在重新加载之间保持不变,您可能需要查看 HTML5localStorage等。

You would need to come up with an age strategy, maybe just dump the current date in there with it as well so you can compare that and expire as needed.

您需要提出一个年龄策略,也许也可以将当前日期与它一起转储到那里,以便您可以进行比较并根据需要过期。

回答by andrew

I would suggest storing your json data to a session. On first page load you can write a script to get your json data, then store them into a session. on each page load/refresh afterwards you can check our session to decide what to do - use the session data or fetch again your json data.

我建议将您的 json 数据存储到会话中。在第一页加载时,您可以编写一个脚本来获取 json 数据,然后将它们存储到会话中。在每个页面加载/刷新之后,您可以检查我们的会话以决定要做什么 - 使用会话数据或再次获取您的 json 数据。

This approach suites me for small scale data (for example: an array of products - colors - sizes - prices).

这种方法适合小规模数据(例如:一系列产品 - 颜色 - 尺寸 - 价格)。

Based on your data you should test you loading times.

根据您的数据,您应该测试加载时间。

回答by Zo72

Thinking out of the box here:

在这里开箱即用:

but if your list has 3000 lines and growing (as you said) is it possible for you to establish its maximum size ?

但是如果您的列表有 3000 行并且还在增长(如您所说),您是否可以确定其最大大小?

let's say the answer is 10,000 (max) items; then do you really need an ajax call ? you could transfer the data straight away with the page

假设答案是 10,000(最大)个项目;那么你真的需要一个ajax调用吗?你可以直接用页面传输数据

(depending on your architecture of course, you could come out with different solution)

(当然,取决于您的架构,您可以提出不同的解决方案)