react-native-sqlite-storage icon indicating copy to clipboard operation
react-native-sqlite-storage copied to clipboard

Possible Unhandled Promise Rejection

Open rollsroyc3 opened this issue 6 years ago • 7 comments

A user recently ran into an issue with a database that the app downloads and installs. So I did some testing and tried to reproduce it.

So the current workflow is:

  1. Open app
  2. Download DB
  3. Install DB
  4. Then the user can select parts from the WarehouseInventory table in the database.

To recreate the issue, after install I renamed the db in the ios simulator so it could not find the db/table.

Expected Behavior

I expected to hit my catch on the promise, to which I could handle the issue and move on.

Current Behavior

It creates a new database, which makes sense. But then doesn't find the table and throws this error in yellowbox.

YellowBox.js:67 Possible Unhandled Promise Rejection (id: 0):
Object {
  "code": 5,
  "message": "no such table: WarehouseInventory",
}

Steps to Reproduce (for bugs)

  1. Install a db in ios simulator
  2. Rename db in finder ios simulator folder
  3. Execute a query

Context

Im unable to catch exceptions when we have a sqlite error, which causes issues for our users.

Your Environment

  • React Native SQLite Storage Version used: 4.1.0
  • React Native version used: 0.59.4
  • Operating System and version (simulator or device): iOS 12.1 iPhone XR

Debug logs

selectDatasetFromPriceBookByPN 420420
RCTLog.js:47 target database location: nosync
RCTLog.js:47 Opening db in mode READ_WRITE, full path: /Users/andrew/Library/Developer/CoreSimulator/Devices/EF39EF12-4775-42A8-89D3-DBE4EBFFE22C/data/Containers/Data/Application/F9FF7B1E-89D6-4338-AA10-745BA32257CC/Library/LocalDatabase/PriceBook_2019_9_30.sqlite
RCTLog.js:47 Database opened
RCTLog.js:47 Good news: SQLite is thread safe!
RCTLog.js:47 open cb finished ok
YellowBox.js:67 Possible Unhandled Promise Rejection (id: 0):
Object {
  "code": 5,
  "message": "no such table: WarehouseInventory",
}

I also found a few other people that mention Possible Unhandled Promise Rejection but no solutions..

https://github.com/andpor/react-native-sqlite-storage/issues/213 https://github.com/andpor/react-native-sqlite-storage/issues/277 https://github.com/andpor/react-native-sqlite-storage/issues/346 https://github.com/andpor/react-native-sqlite-storage/issues/360

rollsroyc3 avatar Sep 30 '19 13:09 rollsroyc3

Here is some of the code for install, running, etc..

export const installPriceBookDatabase = () => {
  console.log("installPriceBookDatabase");
  let success = false;

  return new Promise((resolve, reject) => {
    SQLite.openDatabase(
      { name: getDatabaseName(Utils.getToday()), location: getDatabaseURI() },
      db => {
        db.transaction(tx => {
          tx.executeSql("SELECT * FROM sqlite_master", []).then(
            ([tx, { rows }]) => {
              //RepairsMade, ReportedProblems, WarehouseInventory
              if (rows.raw().length > 2) {
                success = true;
              } else {
                success = false;
              }
            }
          );
        }).then(() => {
          db.close();
          resolve(success);
        });
      },
      error => {
        console.log("Error installing DB", error);
        reject();
      }
    );
  });
};

As you can see below, I would expect a catch to fire here when I rename the DB, but instead I just get the YellowBox error Possible Unhandled Promise Rejection (id: 0):

export const selectFromPriceBookByIID = iid => {
  console.log("selectFromPriceBookByIID", iid);

  return new Promise((resolve, reject) => {
    SQLite.openDatabase(
      { name: getDatabaseName(Utils.getToday()), location: getDatabaseURI() },
      db => {
        db.transaction(tx => {
          tx.executeSql("SELECT * FROM WarehouseInventory WHERE IID=?", [iid])
            .then(([tx, { rows }]) => {
              try {
                resolve(JSON.parse(rows.item(0).PAYLOAD));
              } catch (e) {
                console.log("ttttttttt");
                resolve({});
              }
            })
            .catch(error => {
              console.log("tessttttt");
              console.log(error);
              reject(error);
            });
        }).then(() => {
          db.close();
        });
      },
      error => {
        console.log("Error selecting from DB", error);
        reject(error);
      }
    );
  });
};

rollsroyc3 avatar Sep 30 '19 13:09 rollsroyc3

Looking into the code more I came across rejectOnError in sqlite.js, I commented out the if check and I actually hit my catch (although it also still says Possible Unhandled Promise Rejection).

Is there any specific reason this is set to false for executeSQL? And why is it the only config that rejectOnError is false?

// meaning: [returnValueExpected,prototype,fn,argsNeedPadding,reverseCallbacks,rejectOnError] [false,"SQLitePluginTransaction","executeSql",true,false,false],

Also came across this that discusses it a little https://github.com/andpor/react-native-sqlite-storage/issues/260

rollsroyc3 avatar Sep 30 '19 14:09 rollsroyc3

@andpor any insight?

rollsroyc3 avatar Sep 30 '19 14:09 rollsroyc3

@rollsroyc3 very sorry have been extremely busy and had not had time to look into this...

andpor avatar Mar 24 '20 19:03 andpor

I follow the below blog to integrate SQLite

it's working great and here also provide a solution for promise rejection.

https://medium.com/infinitbility/react-native-sqlite-storage-422503634dd2

Satur-nity avatar Apr 02 '20 05:04 Satur-nity

Personally I don't use the enable Promises function, it cause weird behavior sometimes. I prefer to create a new function with a promise and put my queries in it

The exemple below show a function to select from a table in a very basic way, I'm still learning :)

export async function _select(table: string, columns: Array<String>, aliases?: Array<String>, conditions?: Array<String>) {
    return new Promise<ResultSet>((resolve, reject) => {
        db.transaction(tx => {
            tx.executeSql(`SELECT ${columns} FROM ${table}`, [], (undefined, results) => {
                resolve(results);
            }, reject);
        });
    });
}; 

and when I want to use it in an "await" way, I'm calling the function like that

const results = await _select(**my parameter**s)

the results object will look like that : {"insertId": undefined, "rows": {"item": [Function item], "length": 3, "raw": [Function raw]}, "rowsAffected": 0}

You can take this function or create yours ;)

I inspired myself from this website https://infinitbility.com/react-native-sqlite-storage-examples-of-query#create-table-query

I hope it can help

ghost avatar Aug 24 '21 14:08 ghost