react-native-sqlite-storage
react-native-sqlite-storage copied to clipboard
Possible Unhandled Promise Rejection
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:
- Open app
- Download DB
- Install DB
- 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)
- Install a db in ios simulator
- Rename db in finder ios simulator folder
- 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
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);
}
);
});
};
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
@andpor any insight?
@rollsroyc3 very sorry have been extremely busy and had not had time to look into this...
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
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