【问题标题】:Where to place function that loads json data?在哪里放置加载 json 数据的函数?
【发布时间】:2018-11-30 14:59:28
【问题描述】:

我正在开发使用.json 文件作为主要数据源的项目。应用程序是用 Bootstrap、JavaScript/jQuery 和 HTML5 开发的。这段代码是几个月前开发的,我正在努力提高效率并更新代码。

查看代码后,我注意到的第一件事是数据包含在此应用程序中的方式。用于不同屏幕的.json 文件很少。这些文件遍布不同位置。

而且每次他们执行onclick 时,他们都会重新加载.json 文件。没有理由这样做,因为数据每月更新一次。我想知道为什么这不会只执行一次(第一次加载应用程序时)然后在js 对象中设置数据?

这是一个好的做法还是有更好的做法?以下是我正在考虑如何更新此代码的示例:

var jsonData = {};
$(document).ready(function() {
  $.getJSON('data.json', function(data){ 
    // Load JSON data in JS object.
    jsonData = data;
  });
});

上面的代码应该放在html的header还是body标签中?我知道现在.js 文件包含在body 标签的底部,所有.css 都在header 中。包含 json 文件有什么区别吗?如果有人有任何建议,请告诉我。 json 文件有大约 600 多条记录,其中包含多个字段(超过 30 个)。这在未来可能会改变。因此,如果这些文件变大,我需要确保这不会影响整个应用程序的效率。

【问题讨论】:

  • 您可以将数据存储在会话 cookie 中吗?只需确保在更改数据时您将获得更新的数据。这可以通过缓存 json 文件的字符串来完成。
  • @ZachM。我以前从未使用会话 cookie 这样做过。那是比 js 对象更好的做法吗?这两种方法有什么主要区别吗?你能提供一些例子吗?谢谢。
  • 您将在会话 cookie 中存储 JSON:*.com/questions/42020577/…
  • @ZachM。 localStorage 不是 cookie。使用 cookie 没有意义
  • 本题征求意见。

标签: javascript jquery json single-page-application geojson


【解决方案1】:

在我看来,您认为不应通过 onclick 事件加载文件是正确的。我同意你的观点,你应该事先加载文件。

正确的加载位置是在使用它们的任何 js 代码之前。 JS 被放置在页面底部,因为 DOM 必须已经加载才能使 JS 代码工作。所以很自然地你描述了页面然后加载在它上面运行的代码。

即使有 30 个字段,600 多条记录也是可以轻松放入内存的最小数据量。我会预先加载所有 json 并直接从内存中的变量中使用它们。如果您认为这会增长很多(我的意思是 100.000 多条记录),那么我会使用 localstorage。

不过,我会给你另一种选择:在我的一个系统中,我加载到内存 aprox。一个完整的内存数据库中有 25000 条记录,这发生在不到 1 秒的时间内,并且立即选择该数据库。你有完整的 sql 可用。这对你来说可能是一个很好的方法。 我说的是编译成 javascript 的 SQLite:https://github.com/kripken/sql.js/

我测试了一些内存数据库,强烈推荐这个。

编辑

回复@expresso_coffee:

我使用以下代码将json导入SQLite(我使用requireJs):

define(['jquery', 'sqlite', 'json!data/data.json'],
function($, sqlite, jsonData) {

    self = {};

    var db;

    function createDb() {
        return new Promise((res)=>{
            db = new sqlite.Database();
            db.run("CREATE VIRTUAL TABLE usuarios USING fts4(field1 int, field2 text, field3 text, field4 text, field5 text, field6 text, field7 text);");
            res(1);
        })
    }

    function populateDB( jsonData ) {
        return new Promise((res)=>{
            var stmt = db.prepare("INSERT INTO table values (?,?,?,?,?,?,?)");
            db.run("BEGIN TRANSACTION");
            jsonData.list.forEach((rec)=>{
                stmt.run([rec.field1, rec.field2, rec.field3, rec.field4, rec.field5, rec.field6, rec.field7);
            })
            stmt.finalize;
            db.run("END");
            updateDOM();
            res(1);
        });
    }

    (...)

这是在瞬间加载 25000 条记录的代码。

【讨论】:

  • Nelson,感谢您的解释和提供有用的反馈。截至目前,我们使用 Oracle 数据库。我不确定 SQLite 是否可以在系统中轻松实现,或者是否需要进行重大更改/更新。另外,您是否建议将getJson 函数放在.js 文件中,然后将其作为第一个脚本标记包含在body 标记中?或者应该在 html 文件顶部的 head 中,如我在上面的示例中所示。谢谢!
  • 头部不应该有 JS。所有这些都应该在底部。我告诉您的 SQLite 版本不是您系统中的可安装数据库。这是一个 js 编译的数据库。您只需在代码中包含一个 js 文件,就可以使用内存中的完整数据库了。所以你不需要安装任何东西。
  • 关于是否应该在文件中使用,取决于加载js的代码有多大。我的理解是,这个代码长度只有几行。如果是这种情况,您可以将其包含在 js 初始化代码中。
  • 我还有一个关于 SQLite 的问题。这是所有浏览器都支持的东西吗?这也适合带有 AngularJS 或 ReactJS 等框架的单页应用程序吗?我开始阅读有关该内容的信息,但只是想确保我朝着正确的方向前进。这个应用程序是单页的,我将来可能会使用 Angular 或 React 来替换 JQuery。
  • AFAIK 是的。如果您在浏览器中遇到一些错误,请告诉我。我还没有找到。
【解决方案2】:

一种方法是存储 $.getJSON 承诺,这样您就只需向每个 url 的服务器发出一个请求(当实际需要时),并在未来对相同数据的任何调用中重复使用相同的承诺

var getData = (function() {
  var baseUrl = 'http://jsonplaceholder.typicode.com/';
  var promises = {};

  function getData(url) {
    console.log(promises[url] ? 'Existing promise' : 'New request', ' URL ::', url)
    promises[url] = promises[url] || $.getJSON(baseUrl + url);
    return promises[url];
  }
  return getData;

})();


// do multiple requests    
getData('todos').then(function(res) { /* do something with results*/ })
getData('todos').then(function(res) {
  console.log(' Second request array length=',res.length)
})

getData('todos/1')
getData('todos/1')
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

【讨论】: