【问题标题】:Unable to run a loop to update Object Array in SQLite with React Native无法运行循环以使用 React Native 更新 SQLite 中的对象数组
【发布时间】:2020-09-30 07:12:09
【问题描述】:

所以这一直困扰着我一段时间,我有一个对象数组,我想插入到我的 SQLite DB 中。每个对象都有 5 个参数,我有 SQL 查询来运行它。我使用循环遍历数组并通过数据库事务将每个对象填充到 SQLite。但是,数据库任务是异步的,这导致循环在任务运行之前完成,并且不正确的数据被填充到数据库中。下面代码中的while循环不起作用,我用for循环尝试了同样的事情,但无济于事。

var i=0;
while(i<rawData.length){
  console.log(rawData[i],i)
   db.transaction(function (tx) {
  console.log(rawData,i," YAY")
          tx.executeSql(
              'Update all_passwords SET title=?,userID=?,password=?,notes=?,category=? WHERE ID =? ',
              [rawData[i].title,rawData[i].userID,rawData[i].password,rawData[i].notes,rawData[i].category,rawData[i].id],
              (tx, results) => {
                console.log("saved all data")
                 tx.executeSql(
                  "SELECT * FROM all_passwords ORDER BY id desc",
                  [],
                  function (tx, res) {
                    i++
                    console.log("Print Out Correct Data")
                    for(var i=0;i<res.rows.length;i++){

                      console.log(res.rows.item(i), i )
                    }
                      });
              }
            );
          console.log("EXIT")
          }

          ,
          (error) => {
                    console.log(error);
                  }
          );
}

我不熟悉使用带有钩子的异步任务,但我相信这可能是一个潜在的解决方案。我的目的是在使用状态来维护加载屏幕的同时将对象的 rawaData 数组一次性填充到 SQLDb 中。

我确实参考了以下来源,但无法提出任何具体的建议。

react native insertion of array values using react-native-sqlite-storage

https://medium.com/javascript-in-plain-english/how-to-use-async-function-in-react-hook-useeffect-typescript-js-6204a788a435

提前致谢!

【问题讨论】:

    标签: javascript reactjs react-native sqlite


    【解决方案1】:

    我为你写了一些关于我将如何解决它的文章。阅读代码中的 cmets。如果有什么不清楚的欢迎随时提问!

    const rawData = [
        { title: "title", userID: "userID", password: "password", notes: "notes", category: "category", id: "id" },
        { title: "title_1", userID: "userID_1", password: "password_1", notes: "notes_1", category: "category_1", id: "id_1" },
        { title: "title_2", userID: "userID_2", password: "password_2", notes: "notes_2", category: "category_2", id: "id_2" }
    ];
    
    // You can mostly ignore this. It's just a mock for the db
    const db = {
        tx: {
            // AFAIK if there is a transaction it's possible to execute multiple statements
            executeSql: function(sql, params, success, error) {
                // just for simulating an error
                if (params.title === "title_2") {
                    error(new Error("Some sql error"));
                } else {
                    console.log(sql, params.title);
                    success();
                }
            }
        },
        transaction: function(tx, error) {
            // simulating async
            setTimeout(() => {
                return tx(this.tx);
            }, parseInt(Math.random() * 1000));
        }
    }
    
    // Lets make a class which handles our dataccess in an async way
    class DataAccess {
        // as transaction has callback functions it's wrapped in a promise
        // on success the transaction is resolved
        // if there is an error it will be thrown
        transaction = () => {
            return new Promise(resolve => {
                db.transaction(tx => resolve(tx), error => {
                    throw error;
                });
            });
        }
    
        // the actual executeSql function which "hides" all the transaction stuff
        // awaits a transaction and executes the sql on it
        // if the execution was successfull resolve
        // if not throw the error
        executeSql = async(sql, params) => {
            const tx = await this.transaction();
            tx.executeSql(sql, params, () => Promise.resolve(), error => {
                throw error;
            });
        }
    }
    
    const dal = new DataAccess();
    // all sql execute tha was possible
    async function insert_with_execute() {
        // promise all does not guarantee execution order
        // but it is a possibility to await an array of promises (async functions)
        await Promise.all(rawData.map(async rd => {
            try {
                await dal.executeSql("sql_execute", rd);
            } catch (error) {
                console.log(error.message);
            }
        }));
    }
    // no sql executed cause of error and all in the same transaction
    async function insert_with_transaction() {
        const tx = await dal.transaction();
        for (let i = 0; i < rawData.length; i++) {
            tx.executeSql("sql_transaction", rawData[i], () => console.log("success"), error => console.log(error.message));
        }
    }
    
    async function test() {
        await insert_with_execute();
        console.log("---------------------------------")
        await insert_with_transaction();
    }
    
    test();

    【讨论】:

      【解决方案2】:

      显然,最好的方法是使用匿名函数,为 i 的每个值创建一个单独的执行实例。这是如何做到这一点的一个很好的例子......

      Javascript SQL Insert Loop

      【讨论】:

      • 如果这是您的解决方案,请使用 let 而不是 var
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多