react native making calls at the startup of the application to the database stuck

Im using expo-sqlite to making calls to the database. the problem is when i make a calls at the application startup. the calls get stuck somehow. never ending, and the application keep waiting.

This is my repository…

import BaseModule from '../baseModule';
import * as SQLite from 'expo-sqlite';
import * as MediaLibrary from 'expo-media-library';
import * as FileSystem from 'expo-file-system';
import * as Permissions from 'expo-permissions';
import {DetaliItemSettings, NovelReaderSettings, ChapterSettings} from '../';
import httpClient from '../http';
import includedParser from '../../includedParser';
import '../../interface/extension'

export type NovelReaderSettingsType = (items: BaseModule) => void;
export type Find = (foundItems: BaseModule[]) => void;
export default class Repository {
  static dbIni: Boolean;
  static selectedParser?: number
  databaseName: string;
  constructor() {
    this.databaseName = 'NovelManager.db';
  }

  getParser =async()=> {
    const parsers = includedParser();

    if (Repository.selectedParser)
        return parsers[Repository.selectedParser??0];
    var novelReader =
        (await this.findOne<NovelReaderSettings>('ApplicationSettings'))
      ? (await this.findOne<NovelReaderSettings>('ApplicationSettings'))
      : (await this.save(NovelReaderSettings.default())) as NovelReaderSettings; 

      Repository.selectedParser = novelReader?.selectedParserIndex
      return parsers[Repository.selectedParser??0];
  }

  importSettings = async (uri: string) => {
    try {
      const {status} = await Permissions.askAsync(Permissions.MEDIA_LIBRARY);
      if (status === 'granted') {
        var json = await FileSystem.readAsStringAsync(uri, {encoding: 'utf8'});
        if (json) console.log(json);
        var item = JSON.parse(json) as {
          applicationSettings: any;
          items: DetaliItemSettings[];
        };
        var appSettings = await this.where('ApplicationSettings');
        if (item.applicationSettings) {
          item.applicationSettings = httpClient.cloneItem(
            appSettings.length > 0 ? appSettings[0] : {},
            item.applicationSettings,
            ['id', 'tableName'],
          );
          await this.save(
            item.applicationSettings,
            undefined,
            'ApplicationSettings',
          );
        }

        if (item.items && item.items.length > 0) {
          for (var i = 0; i < item.items.length; i++) {
            var a = item.items[i];
            var b = await this.where<DetaliItemSettings>('DetaliItems', {
              novel: a.novel,
            })
            var aChapterSettings =
              a.chapterSettings ?? ([] as ChapterSettings[]);
            var bChaptersSettings =
              b && b.length > 0
                ? ((await this.where<ChapterSettings>('Chapters', {
                    detaliItem_Id: b[0].id,
                  })))
                : ([] as ChapterSettings[]);
            var updatedChapterSettings = [] as ChapterSettings[];
            if (b && b.length > 0) {
              if (a.chapterIndex) b[0].chapterIndex = a.chapterIndex;
              b[0].isFavorit = true;
              a = b[0];
            }

            aChapterSettings.forEach((x) => {
              var bCh = bChaptersSettings.find(
                (a) => a.chapterUrl === x.chapterUrl,
              );
              if (bCh)
                updatedChapterSettings.push(
                  httpClient.cloneItem(bCh, x, ['id', 'tableName']),
                );
              else updatedChapterSettings.push(x);
            });

            let detaliItemSettings = await this.save<DetaliItemSettings>(
              a,
              undefined,
              'DetaliItems',
            );

            for (var y = 0; y <= aChapterSettings.length - 1; y++) {
              let m = aChapterSettings[y];
              m.detaliItem_Id = detaliItemSettings?.id ?? 0;
              await this.save(m, undefined, 'Chapters');
            }
          }
        }

        return true;
      }
    } catch (error) {
      console.log(error);
    }
    return false;
  };

  exportFileToDownloadFolder = async () => {
    try {
      const {status} = await Permissions.askAsync(Permissions.MEDIA_LIBRARY);
      if (status === 'granted') {
        var favoriteData = await this.where<DetaliItemSettings>('DetaliItems', {
          isFavorit: true,
        });
        for (var i = 0; i < favoriteData.length; i++) {
          var item = favoriteData[i];

          item.chapterSettings = await this.where<ChapterSettings>('Chapters', {detaliItem_Id: item.id});
          item.id = 0;
          item.chapterSettings.forEach((x) => {
            x.id = 0;
            x.detaliItem_Id = 0;
          });
        }

        var result = {
          applicationSettings: await this.findOne<NovelReaderSettings>('ApplicationSettings'),
          items: favoriteData,
        };

        let fileUri = FileSystem.documentDirectory + 'NovelManager.db';
        await FileSystem.writeAsStringAsync(fileUri, JSON.stringify(result), {
          encoding: FileSystem.EncodingType.UTF8,
        });
        const asset = await MediaLibrary.createAssetAsync(fileUri);
        await MediaLibrary.createAlbumAsync('Download', asset, false);

        return true;
      }
    } catch (error) {
      console.log(error);
    }
    return false;
  };

  dataBasePath = () => {
    return FileSystem.documentDirectory + this.databaseName;
  };
  createConnection = () => {
    return SQLite.openDatabase(this.databaseName);
  };

  allowedKeys = (tableName: string) => {
    return new Promise((resolve, reject) => {
      this.createConnection().transaction(
        (x) =>
          x.executeSql(
            `PRAGMA table_info(${tableName})`,
            undefined,
            (trans, data) => {
              var keys = [] as string[];
              for (var i = 0; i < data.rows.length; i++) {
                if (data.rows.item(i).name != 'id')
                  keys.push(data.rows.item(i).name);
              }
              resolve(keys);
            },
          ),
        (error) => {
          reject(error);
        },
      );
    }) as Promise<string[]>;
  };

 async selectLastRecord<T> (item: BaseModule)  {
    console.log('Executing SelectLastRecord...');
    return  (await this.find(item.id <= 0 ? `SELECT * FROM ${item.tableName} ORDER BY id DESC LIMIT 1;` : `SELECT * FROM ${item.tableName} WHERE id=?;`,item.id > 0 ? [item.id] : undefined)).toType<T>().single<T>()
    
  };

  delete = async (item: BaseModule, tableName?: string) => {
    tableName = item.tableName ?? tableName;
    var q = `DELETE FROM ${tableName} WHERE id=?`;
    await this.execute(q, [item.id]);
  };

  public save<T> (
    item?: BaseModule,
    insertOnly?: Boolean,
    tableName?: string,
  )  {
    if (!item)
        return undefined;
    if (!item.tableName) item.tableName = tableName ?? '';
    return new Promise(async (resolve, reject) => {
      try {
        await this.setUpDataBase();
        console.log('Executing Save...');
        var items = await this.where(item.tableName, {id: item.id});
        var keys = (await this.allowedKeys(item.tableName)).filter((x) =>
          Object.keys(item).includes(x),
        );
        let query = '';
        let args = [] as any[];
        if (items.length > 0) {
          if (insertOnly) return;
          query = `UPDATE ${item.tableName} SET `;
          keys.forEach((k, i) => {
            query += ` ${k}=? ` + (i < keys.length - 1 ? ',' : '');
          });
          query += ' WHERE id=?';
        } else {
          query = `INSERT INTO ${item.tableName} (`;
          keys.forEach((k, i) => {
            query += k + (i < keys.length - 1 ? ',' : '');
          });
          query += ') values(';
          keys.forEach((k, i) => {
            query += '?' + (i < keys.length - 1 ? ',' : '');
          });
          query += ')';
        }
        keys.forEach((k: string, i) => {
          args.push(item[k] ?? null);
        });
        if (items.length > 0) args.push(item.id);

        await this.execute(query, args);
        if (item["selectedParserIndex"])
            Repository.selectedParser = item["selectedParserIndex"] as number;
        resolve((await this.selectLastRecord<T>(item)));
      } catch (error) {
        console.log(error);
        reject(error);
      }
    }) as Promise<T>;
  };

  public find = (query: string, args?: any[]) => {
    return new Promise((resolve, reject) => {
      this.createConnection().transaction(
        async (x) => {
          await this.setUpDataBase();
          console.log('Executing Find..');
          x.executeSql(
            query,
            args,
            async (trans, data) => {
              console.log('query executed:' + query);
              var items = [] as BaseModule[];
              for (var i = 0; i < data.rows.length; i++) {
                var t = data.rows.item(i);
                items.push(t);
              }
              resolve(items);
            },
            (_ts, error) => {
              console.log('Could not execute query:' + query);
              console.log(error);
              reject(error);
              return false;
            },
          );
        },
        (error) => {
          console.log(error);
          reject(error);
        },
      );
    }) as Promise<BaseModule[]>;
  };

  async where<T>  (tableName: string, query?: any) {
    var q = `SELECT * FROM ${tableName} ${query ? 'WHERE ' : ''}`;
    var values = [] as any[];
    if (query) {
      Object.keys(query).forEach((x, i) => {
        q += x + '=? ' + (i < Object.keys(query).length - 1 ? 'AND ' : '');
        values.push(query[x]);
      });
    }
    return (await this.find(q, values)).map((x) => {
      x.tableName = tableName;
      return x;
    }).toType<T>() ?? [];
  };


  async findOne<T> (tableName: string, query?: any)  {
    var items = await this.where<T>(tableName, query);
    return items.single<T>();
  };

  execute = async (query: string, args?: any[]) => {
    return new Promise((resolve, reject) => {
      this.createConnection().transaction(
        (tx) => {
          console.log('Execute Query:' + query);
          tx.executeSql(
            query,
            args,
            (tx, results) => {
              console.log('Statment has been executed....' + query);
              resolve(true);
            },
            (_ts, error) => {
              console.log('Could not execute query');
              console.log(args);
              console.log(error);
              reject(error);
              return false;
            },
          );
        },
        (error) => {
          console.log('db executing statement, has been termineted');
          console.log(args);
          console.log(error);
          reject(error);
          throw 'db executing statement, has been termineted';
        },
      );
    });
  };

  public dropTables = async () => {
    await this.execute(`DROP TABLE if exists ApplicationSettings`);
    await this.execute(`DROP TABLE if exists DetaliItems`);
    await this.execute(`DROP TABLE if exists Chapters`);
    Repository.dbIni = false;
    await this.setUpDataBase();
  };

  setUpDataBase = async () => {
    let applicationSetupQuery = `CREATE TABLE if not exists ApplicationSettings (
      id	INTEGER NOT NULL UNIQUE,
      backGroundColor	TEXT NOT NULL,
      fontSize INTEGER NOT NULL,
      lineHeight INTEGER NOT NULL,
      fontFamily TEXT NOT NULL,
      marginLeft INTEGER NOT NULL,
      marginRight INTEGER NOT NULL,
      detaliItem_Id	INTEGER,
      selectedParserIndex INTEGER,
      PRIMARY KEY(id AUTOINCREMENT)
    );`;

    let detaliItemsQuery = `CREATE TABLE if not exists DetaliItems (
      image	TEXT NOT NULL,
      title	TEXT NOT NULL,
      description	TEXT NOT NULL,
      novel	TEXT NOT NULL,
      parserName TEXT NOT NULL,
      chapterIndex INTEGER NOT NULL,
      id INTEGER NOT NULL,
      isFavorit INTEGER NOT NULL,
      PRIMARY KEY(id AUTOINCREMENT)
    );`;

    let chapterQuery = `CREATE TABLE if not exists Chapters (
      id INTEGER NOT NULL UNIQUE,
      chapterUrl TEXT NOT NULL,
      isViewed INTEGER NOT NULL,
      currentProgress	NUMERIC NOT NULL,
      finished INTEGER NOT NULL,
      detaliItem_Id	INTEGER NOT NULL,
      PRIMARY KEY(id AUTOINCREMENT),
      CONSTRAINT "fk_detaliItem_id" FOREIGN KEY(detaliItem_Id) REFERENCES DetaliItems(id)
    );`;

    if (!Repository.dbIni) {
      console.log('dbIni= false, setUpDataBase');
      await this.execute(applicationSetupQuery);
      await this.execute(detaliItemsQuery);
      await this.execute(chapterQuery);
      Repository.dbIni = true;
    } else {
      console.log('dbIni= true, setUpDataBase');
    }
  };
}

and when i call await new Repository().getParser() it gets stuck and never end.

Hey @alentoma, your code example contains external assets and implementations. Can you please provide a runnable, public example that we can attempt to reproduce the behavior with?

Cheers,
Adam

Dont need, I already solved the problem. The problem did not have anything to do with expo :slight_smile:

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.