WebSQL-запросы зависают, никогда не возвращая успешных или ошибочных обратных вызовов - PullRequest
0 голосов
/ 21 мая 2019

У меня есть процесс инициализации для веб-приложения, которое рекурсивно выполняет запросы WebSQL.

Он включает в себя массив с именем actions, и к этому массиву добавляются несколько функций. Каждая функция возвращает обещание, которое разрешается при выполнении запроса WebSQL. Большинство из этих функций включают проверку наличия в таблице всех столбцов, которые она должна иметь, и, если нет, удаление таблицы и воссоздание ее с правильной конфигурацией столбцов. (Данные пользователя хранятся на стороне сервера, поэтому при следующем входе в систему таблицы будут заполнены.)

Каждая функция в массиве должна завершиться до того, как начнется следующая. Базовая основа каждой функции в массиве actions такова:

actions.push(function() {
var d = $q.defer();
    Database.recreateTable(table).then(function() {
        d.resolve("Success");
    }, function(e) { d.resolve(e);});
    return d.promise
})

(Строка, которая разрешается даже в случае сбоя функции базы данных, служит для проверки выполнения последующих таблиц.)

Database.recreateTable - это функция в службе Angular:

var recreateTable = function(table) {
    var def = $q.defer();
    execute("DROP TABLE IF EXISTS " + table).then(function() {
        createTable(table).then(function() {
            def.resolve();
        }, function(error) {
            ValidatorService.log(getScriptName(), error);
            def.reject(error);
        });
    }, function (error) {
        ValidatorService.log(getScriptName(), error);
        def.reject(error);
    });
    return def.promise;
}

, где createTable - это просто следующее:

var createTable = function(table) {
    var def = $q.defer();
    var q = "CREATE TABLE IF NOT EXISTS " + table + " (" + getColumns(table, true, true) + ")";
    execute(q).then(function(s) {
        def.resolve();
    }, function (error) {
        def.reject(error);
    });
    return def.promise;
}

и execute - это оболочка для транзакций WebSQL, которая охватывает как веб-использование, так и использование Cordova:

var execute = function (query, bindings) {

    bindings = typeof bindings !== 'undefined' && typeof bindings !== 'null' ? bindings : [];
    var deferred = $q.defer();

    if (db === undefined || db === null) { //initialize first if hasn't been done yet
        init().then(executeQuery(), function(error) {} );
    }
    else {
        executeQuery();
    }

    function executeQuery() {
        if (window.cordova) {
            $cordovaSQLite.execute(db, query, bindings).then(function (result) {
                deferred.resolve(result);
            }, function (fail) {
                ValidatorService.log(getScriptName(), JSON.stringify(fail));
                deferred.reject(fail);
            });
        }
        else {
            db = window.openDatabase("database.db", '1.0', 'auto', 1024 * 1024 * 100);
            db.transaction(function(tx) {
                tx.executeSql(query, bindings, function (tx, result) {
                    deferred.resolve(result);
                }, function (tx, fail) {
                    deferred.resolve(fail);
                });
            });
        }
    }

    return deferred.promise;
}

Все функции в массиве actions выполняются одна за другой со следующим кодом:

function executeRun() {
    var d = $q.defer();
    function multi(i) {
        if (actions.length > 0 && i < actions.length) {
            actions[i]().then(function(s) {
                multi(i+1);
            }, function(e) {
                multi(i+1);
            })
        }
        else {
            d.resolve();
        }
    }
    multi(0);
    return d.promise;
}

В данный момент написано, чтобы продолжить, независимо от того, успешно ли выполнено действие, так что последующие таблицы все равно проверяются, несмотря ни на что. Действия выполняются одно за другим, а не асинхронно, потому что некоторые действия могут быть или не быть добавлены в зависимости от более ранних записей в массиве actions.

Идея, стоящая за этим, кажется довольно простой, но проблема в том, что после нескольких итераций в цикле запрос просто зависает и не возвращает ответ, поэтому никогда не запускаются обратные вызовы об успешном завершении и об ошибке. Кажется, что не существует какой-либо рифмы или причины, по которой это происходит в тот момент, когда это происходит, и это происходит только в iOS Cordova, когда другие процессы, которые зависят от этих таблиц, возвращают ошибки «таких таблиц нет». В Android Cordova такой проблемы нет.

Я видел, как это происходило в Chrome для настольных компьютеров раньше, оно не остановится даже после нажатия кнопки «Очистить данные сайта». Единственное, что исправило это, это переустановка Chrome.

...