Developing sqllite public method with uni app (h5 using sqllite for synchronous and asynchronous problems)

Basic information of the project

Using uni app development, the client selects sqllite for local data storage

Uni app reference address

Uni app official website (dcloud.io)

sqllite reference address

HTML5+ API Reference (html5plus.org)

Solutions to asynchronous

Asynchronously executed code generally has callbacks. Create your own callback function in the outer method to realize business operations through callbacks and realize the logic of "synchronous execution".

development process

Due to business needs, local data storage is required at the app client. I have been developing java all the year round, and the object-oriented concept is deeply rooted in the hearts of the people, so I need to write a dbutils in the right place JS tool class, which provides methods for database addition, deletion, modification and query, and returns execution results. However, during the debugging process, it is found that the method of sqllite operating the database is asynchronous, so the correct results can not be obtained according to the traditional return value method.

Initial idea: first define the return result variable, and then return the result after the operation is completed

// This method doesn't work!
export function executeSql(sql){
	let result = false;
	// Open database
    plus.sqlite.openDatabase({
    	// Database name
    	name: 'xxxxx',
    	// Database file path
    	path: '_doc/xxxxx.db',
    	// Database opened successfully
    	success: function(e){
    		result = true;
    	},
		fail:function(e){
			console.log(e);
		}
    });
	if (result) {
		// Execute sql
		plus.sqlite.executeSql({
			name:'xxxxx',
			sql: sql,
			success(){
				result = true;
			},
			fail(e) {
				console.log(e);
			}
		});
	}
	// close database
	plus.sqlite.closeDatabase({name: 'xxxxx'});
	return result;
}

Through debugging, it is found that the method always returns false when executing plus sqllite. At XXX, js continued to execute without waiting. As a result, the database was closed. Later, I wrote the execution sql in the callback to open the database, and the database was closed in the callback to execute sql. However, it can only solve the problem that the execution sequence of the database operation part is correct, and the return value is still incorrect.

At this time, I want to solve this asynchronous problem violently. I have a naive and bold idea to block the program execution during asynchronous execution and monitor whether the asynchronous operation is completed

	let executeFinished = false;
	......Various database operations, assignment upon completion executeFinished = true;
	while(true) {
		if (executeFinished) {
			break;
		}
	}
	......Subsequent operation

Then it is found that the program card is in while(true), and the callback method of database operation will never be accessed. executeFinished will never change.

After consulting the data, it is found that js is single threaded, so the while(true) loop program is blocked. The asynchronous processing in js is only executed at the right time, and the underlying is not parallel.

Finally, the asynchronous problem of sqllite is solved by passing callback events to public methods

Final code

Tool class: dbutils js

/**
 * Add / delete / modify sql execution
 * @param {Object} sql
 * @param {Object} callback
 */
export function executeSql(sql, callback){
	let result = {};
    // Open database
    plus.sqlite.openDatabase({
    	// Database name
    	name: 'xxxxx',
    	// Database file path
    	path: '_doc/xxxxx.db',
    	// Database opened successfully
    	success: function(e){
    		plus.sqlite.executeSql({
    			name:'xxxxx',
    			sql: sql,
    			success(){
    				result.success = true;
					closeDatabase();
					callback(result);
    			},
				fail(e) {
					result.success = false;
					result.data = e;
					closeDatabase();
					callback(result);
				}
    		});
    	},
		fail:function(e){
			result.success = false;
			result.data = e;
			closeDatabase();
			callback(result);
		}
    });
}
/**
 * Database query select
 * @param {Object} sql
 * @param {Object} callback
 */
export function selectSql(sql, callback){
	let result = {};
    // Open database
    plus.sqlite.openDatabase({
    	// Database name
    	name: 'xxxxx',
    	// Database file path
    	path: '_doc/xxxxx.db',
    	// Database opened successfully
    	success: function(e){
    		plus.sqlite.selectSql({
    			name:'xxxxx',
    			sql: sql,
    			success(data){
    				result.success = true;
					result.data = data;
					closeDatabase();
					callback(result);
    			},
				fail(e) {
					result.success = false;
					result.data = e;
					closeDatabase();
					callback(result);
				}
    		});
    	},
		fail:function(e){
			result.success = false;
			result.data = e;
			closeDatabase();
			callback(result);
		}
    });
}
/**
 * close database
 */
function closeDatabase() {
	plus.sqlite.closeDatabase({name: 'xxxxx'});
}

introduce:

import { executeSql } from '@/common/db/dbUtils.js';

Call:

let sql = "insert into xxxxxxxxxx";
executeSql(sql, function(result) {
	if (result.success) {
		// Business operation
	} else {
		// Failed operation
	}
});

Keywords: html5 SQLite uni-app

Added by Toboe on Tue, 14 Dec 2021 11:51:18 +0200