【问题标题】:Asynchronous SQL insert in loop循环中的异步 SQL 插入
【发布时间】:2012-05-20 07:37:12
【问题描述】:

我在将行插入 SQL 数据库时遇到问题。我想将一组对象转换为 javascript 中的 SQL 表。

以下代码仅添加数组的第一个对象。我已经尝试了在 stackoverflow 和其他地方可以找到的所有内容,但无法使其正常工作。

任何帮助将不胜感激。谢谢。

        for (var i = 0; i < arr.length; i++) {
            db.save({key:i+"", value:arr[i]}, function(e){

            });
        }

更新 1: 我已将其更改为 mathec 的示例并稍微缩小了问题范围。

插入的行数取决于插入对象的大小。所以它与处理每个对象所需的时间有关。

我该如何解决这个问题?谢谢。

更新 2:

我在下面采纳了 Robert Young 的建议,并附上了一个独立的示例。

下面的示例仅插入前 5 个元素。如果我删除了测试键中的一些单词文本,所以它只说“单词”一次,然后插入 10 个元素。所以现在我确定这与处理每个对象所需的时间有关。

<html>
    <head>
        <script src="jquery.js"></script>
        <script src="lawnchair.js"></script>
        <script type='text/javascript'>


            var db = "";
            var arr = [];

            arr.push({name:"a1", test:"word word word word word word word word word word word word word word "});
            arr.push({name:"a2", test:"word word word word word word word word word word word word word word "});
            arr.push({name:"a3", test:"word word word word word word word word word word word word word word "});
            arr.push({name:"a4", test:"word word word word word word word word word word word word word word "});
            arr.push({name:"a5", test:"word word word word word word word word word word word word word word "});
            arr.push({name:"a6", test:"word word word word word word word word word word word word word word "});
            arr.push({name:"a7", test:"word word word word word word word word word word word word word word "});
            arr.push({name:"a8", test:"word word word word word word word word word word word word word word "});
            arr.push({name:"a9", test:"word word word word word word word word word word word word word word "});
            arr.push({name:"a10", test:"word word word word word word word word word word word word word word "});
            arr.push({name:"a11", test:"word word word word word word word word word word word word word word "});

            $(function() {
                db = new Lawnchair({table:'t50'}, function(e){
                    for ( i = 0; i < arr.length; i++) {
                        (function(i) {
                            add_row(i);
                        }(i));
                    }
                });
            });

            function add_row(i) {
                db.save({key:i+"", value:arr[i]}, function(e){

                });
            }

        </script>
    </head>
    <body>

    </body>
</html>

更新 3: 我使用了罗伯特建议的代码,并提出了以下与三个小元素一起使用的代码。所以我改变了第一个元素,使它比其他元素更大来测试它。第一个元素没有添加,最后两个是。处理数组有时间限制吗?

<html>
    <head>
        <script src="jquery.js"></script>
        <script src="lawnchair.js"></script>
        <script type='text/javascript'>

            var arr = [];
            var db = "";

            $(function() {
                db = new Lawnchair({table:'t51'}, function(e){
                    arr=[{key:"k1", value:"v1. Because the contents of this element are larger than the others it will not be added for some reason. Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. "}
                    ,{key:"k2", value:"v2"}
                    ,{key:"k3", value:"v3"}]

                    db.batch(arr, function () {
                        db.all(function (recs) { for (r in recs) {console.log(recs[r].key +"| "+ recs[r].value) } });
                    });
                });

            });

        </script>
    </head>
    <body>
    </body>
</html>

【问题讨论】:

  • 我没有看到您发布的第一个 sn-p 代码有任何问题,除了如果您不使用回调参数,则不需要它。似乎有什么奇怪的事情正在发生。你能发布一个short, self-contained example 的问题吗?
  • 您好罗伯特,我已经添加了您建议的完整示例。有任何想法吗?谢谢。

标签: javascript sql sqlite asynchronous lawnchair


【解决方案1】:

我犯过几次棘手的错误 :-)。如果在循环内调用回调函数,它将被异步调用。因此,您的循环将一直执行到最后。解决这个问题的一种方法是围绕当前 i 值形成一个闭包,这样当回调函数执行时,它就会绑定到右边的 i。像这样的:

function doSomething(i) {
  console.log(i)
}

var i, len;

for ( i = 0; i < 10; i++) {
  (function(i) {
    doSomething(i);
  }(i));
}

循环内的函数将立即执行,但 i 值将保留在作用域内。

【讨论】:

  • 此时您需要缩小可能性。也许尝试记录数组值以确保迭代有效。然后一旦确认,检查数据库日志以确保该行没有因某种原因被拒绝。
  • 嗨,mathec,我缩小了问题的范围。对象越大,插入的行就越少。因此,如果与处理对象所需的时间有关。但不知道是什么。
【解决方案2】:

很难缩小问题的解决方案,因为我们不知道您如何将数据保存到数据库,也许是 AJAX 请求?但我认为问题在于保存每一行的整个逻辑数组异步,因为代码不等待保存一行来启动另一行,所以发生了某种竞争条件,一些行保存在同一个“id”(自动增量字段)中,这解释了为什么只有一些行已保存。

我的建议是将整个数组发送到服务器,然后保存每一行。

当然你可以为每一行做,首先锁定id然后保存数据,但这是一个坏主意,因为你需要为每一行往返于服务器和数据库,使对服务器的请求量翻倍.

希望对你有帮助!

P.D. +1 到 @mathec 回答指出存在回调问题的循环变量!

【讨论】:

  • 你好,Juan,它是存储在本地的,所以不用担心它会被发送到服务器。我将尝试测试您的 ID 假设,但即使我只添加一个稍大的行(只是键中的一段文本),也不会添加任何内容。所以我认为这与元素的大小有关。
【解决方案3】:

首先,由于这是持久化存储,如果你一遍又一遍地运行它,你可能每次都得到不同的结果,因为你没有初始化持久化存储。最好添加db.nuke() 以确保您从一张白纸开始,至少在您解决任何错误之前。

关于异步存储的主要知识是,仅仅因为函数返回并不意味着数据实际上已经存储了。所以如果你跑

db = new Lawnchair(function(db){
    db.save({key:"value"})
    db.get("foo", function (rec) { console.log(rec.value) });
});

它可能会或可能不会起作用,因为当您调用 db.get 时,可能会或可能不会存储该值。

为此,我们需要确保在调用 db.get 之前已存储该值。做到这一点的方法是使用回调——如果你将两个参数传递给 db.save,那么一旦值被存储,它将调用第二个参数。所以

db = new Lawnchair(function(db){
    db.save({key:"foo", value:"bar"}, function () {
        db.get("foo", function (rec) { console.log(rec.value) });
    });
});

工作正常。

当您尝试存储多个值时,这会变得很困难,因为您希望确保所有值都已存储。幸运的是,有一个函数可以做到这一点,batch

db = new Lawnchair(function(db){
    arr=[{key:"k1", value:"v1"},{key:"k2", value:"v2"},{key:"k3", value:"v3"}];
    db.batch(arr, function () {
        db.all(function (recs) { for (r in recs) {console.log(recs[r].key) } });
    });
});

应该输出

k1
k2
k3

试试看会发生什么。

【讨论】:

  • 嗨罗伯特,我试过你的例子,就像我的一样,它只适用于非常少量的数据。如果您将示例中的“k1”替换为更多文本(例如一段),则只会添加最后两个元素。
  • 另一个有趣的事情是当你增加第一个元素的键或值的文本大小时,最后两个元素被添加到数据库中,但是 console.debug 永远不会被调用。这是一个非常奇怪的问题。
  • 这可能是特定于浏览器的问题,因为我没有遇到过这样的问题。您使用的是什么浏览器(版本、操作系统)和 Lawnchair 适配器?您使用的浏览器是否可能不允许您存储大量数据?
  • 谢谢,好像是铬的版本。
猜你喜欢
  • 1970-01-01
  • 2018-09-18
  • 2018-10-17
  • 2021-08-12
  • 2015-03-16
  • 1970-01-01
  • 1970-01-01
  • 2020-03-07
  • 1970-01-01
相关资源
最近更新 更多