【问题标题】:How can I make tx.executeSql() function sync with async/await?如何使 tx.executeSql() 函数与 async/await 同步?
【发布时间】:2021-01-08 21:13:48
【问题描述】:

如何使tx.executeSql(SQL, [], (tx, results) 成为带有sync/await 的同步函数?

我想做一些这样的事情:

tx.executesql 是异步的,所以我的 closeDB() (closeDatabase()) 不起作用,因为事务正在进行中。

await tx.executeSql(sql, [], (tx, results)

但它不起作用。

(查看输出)

这是我在输出末尾得到的警告:

C:\...name of proyect\node_modules\react-native\Libraries\Components\ScrollView\InternalScrollViewType.js:46 Possible Unhandled Promise Rejection (id: 0):
TypeError: error is not a function
TypeError: error is not a function
    at SQLitePlugin.close (blob:http://localhost:8081/7a5bb020-64e9-41f5-a654-e50e6b9f5827:93749:9)
    at _callee4$ (blob:http://localhost:8081/7a5bb020-64e9-41f5-a654-e50e6b9f5827:92942:54)
    at tryCatch (blob:http://localhost:8081/7a5bb020-64e9-41f5-a654-e50e6b9f5827:23006:19)
.
.
.
.
async componentDidMount() {


    console.log('*COMIENZA componentDidMount');
    await this.consultarBD();
    await this.openBD();

    console.log('DataUsuarios es: ' + this.state.dataUsuarios);
    await this.insertarDatos();
    await this.closeDatabase();

    console.log('*TERMINA componentDidMount');

  }
 insertarDatos = async () =>{
    console.log('COMIENZA insertarDatos');
     await db.transaction((tx) => {
       console.log('Comienza Transaction');
        for(let i in this.state.dataUsuarios){
          const sql = `INSERT INTO usuarios VALUES (
            '${this.state.dataUsuarios[i].id}', 
            '${this.state.dataUsuarios[i].nombre}',
            '${this.state.dataUsuarios[i].usuario}',
            '${this.state.dataUsuarios[i].password}',
            '${this.state.dataUsuarios[i].grupo}',
            '${this.state.dataUsuarios[i].faenas}'
          )`;
          console.log('antes de excute i es: ' + i);
          tx.executeSql(sql, [], (tx, results) => {
           console.log('dentro de executesql i es: ' + i);
            if(results.rowsAffected > 0){
              console.log('¡Datos insertados en BD!');
            }else{
              console.log('¡No se puedieron insertar datos en la BD!');
            }(error) => {
            console.log(error.message);
            }
          });
        }
        console.log('termina transaccion');
    });
    
    console.log('TERMINA insertarDatos');

  }

输出:



C:\Users\josen\React-Projects\Ges\src\Screen\Login.js:22 COMIENZA insertarDatos
C:\Users\josen\React-Projects\Ges\src\Screen\Login.js:88 Comienza Transaction
C:\Users\josen\React-Projects\Ges\src\Screen\Login.js:88 antes de excute i es: 0
C:\Users\josen\React-Projects\Ges\src\Screen\Login.js:88 antes de excute i es: 1
C:\Users\josen\React-Projects\Ges\src\Screen\Login.js:88 antes de excute i es: 2
C:\Users\josen\React-Projects\Ges\src\Screen\Login.js:88 antes de excute i es: 3
C:\Users\josen\React-Projects\Ges\src\Screen\Login.js:90 termina transaccion
C:\Users\josen\React-Projects\Ges\src\Screen\Login.js:112 TERMINA insertarDatos
C:\Users\josen\React-Projects\Ges\src\Screen\Login.js:128 Cerrando database ...
C:\Users\josen\React-Projects\Ges\src\Screen\DrawerScreens\index.js:7 cannot close: transaction is in progress
C:\Users\josen\React-Projects\Ges\src\Screen\Login.js:91 dentro de executesql i es: 0
C:\Users\josen\React-Projects\Ges\src\Screen\Login.js:93 ¡Datos insertados en BD!
C:\Users\josen\React-Projects\Ges\src\Screen\Login.js:91 dentro de executesql i es: 1
C:\Users\josen\React-Projects\Ges\src\Screen\Login.js:93 ¡Datos insertados en BD!
C:\Users\josen\React-Projects\Ges\src\Screen\Login.js:91 dentro de executesql i es: 2
C:\Users\josen\React-Projects\Ges\src\Screen\Login.js:93 ¡Datos insertados en BD!
C:\Users\josen\React-Projects\Ges\src\Screen\Login.js:91 dentro de executesql i es: 3
C:\Users\josen\React-Projects\Ges\src\Screen\Login.js:93 ¡Datos insertados en BD!

【问题讨论】:

    标签: javascript reactjs asynchronous async-await


    【解决方案1】:

    制作executeSql()async/await方式:

    async function example() {
      let db = await SQLite.openDatabase(
        database_name,
        database_version,
        database_displayname,
        database_size
      );
    
      await db.transaction(async tx => {
         var [tx, results] = await tx.executeSql("SELECT * from TableName;");
         var row = results.rows.item(0); //get the first row assumed existed.
      });
    
      await db.close();
    }
    

    【讨论】:

    • 这是一个简洁的答案,但我看到您不得不使用两个 var 声明而不是 let 或 const。我试图改变这一点,但 Typescript 抱怨它。我看到您已经进一步使用了 let 。让 async / await 与 sqLite 一起工作并理解它真的很困难。尤其是 [tx, results] 数组的原因。我无法理解 tx 出现在那里的原因。
    • @mwarren, tx 在那里是因为executeSql 是一个异步方法,也许在某个地方你得到了结果仍然需要tx 来执行另一个SQL。
    • 无法正常工作,因为 executeSql 需要回调函数
    【解决方案2】:

    尝试像这样实现它,将它包装在一个 Promise 中,你应该可以使用 await 调用这个函数

      insertarDatos = () => {
        return new Promise((resolve, reject) => {
          db.transaction((tx) => {
            try {
              /* Successful transaction */
              /* Make sure to call resolve when the transaction has finished
              */
              resolve()
            } catch (error) {
              /* Failed transaction */
              // if you reject any eventual errors, you can catch them when calling the function insertarDatos
    
              reject(error)
            }
          });
        })
      }
    

    现在,如果这不起作用,则可能是您的forin 有问题。如果是这种情况,查看此post 可能会很有用。它有一个 async foreach 的本机实现,可以按如下方式实现:

    await asyncForEach(userlist, async (user, index) => {
         // do something with user and index
    
         // you can use await here
    })
    

    【讨论】:

    • 我喜欢这个答案。让您完全掌控。而且很简单
    【解决方案3】:
    async getSqlitedata(): {
       const data = await dbconn.executeSql("SELECT * from TableName;",[]);
       if (data.rows.lenth >0) {
           console.log(data.rows);
       }
    }
    

    它将返回一个对象{rows: {…}, rowsAffected: 0, insertId: undefined}

    【讨论】:

      猜你喜欢
      • 2019-10-31
      • 2014-09-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-08-01
      • 2021-06-06
      • 1970-01-01
      相关资源
      最近更新 更多