Обертывание вызовов WebSQL ExecuteSQL в отложенный / обещание jQuery

#javascript #jquery #html #web-sql

#javascript #jquery #HTML #web-sql

Вопрос:

Спецификация html5 для ExecuteSQL включает в себя успешный обратный вызов и обратный вызов с ошибкой:

 db.transaction(function(tx) {    
    tx.executeSql('SELECT * FROM MyTable WHERE CategoryField = ?', 
    [ selectedCategory ], 
    function (tx, rs) { displayMyResult(rs); }, 
    function (tx, err) { displayMyError(err); } );
});
  

Если бы я использовал jQuery, есть ли способ реализовать это с использованием нового jQuery promise / deferred hotness?

Ответ №1:

Я просто хотел добавить еще один пример.

 (function () {
    // size the database to 3mb.
    var dbSize = 3 * 1024 * 1024,
        myDb = window.openDatabase('myDb', '1.0', 'My Database', dbSize);

    function runQuery() {
        return $.Deferred(function (d) {
            myDb.transaction(function (tx) {
                tx.executeSql("select ? as Name", ['Josh'], 
                successWrapper(d), failureWrapper(d));
            });
        });
    };

    function successWrapper(d) {
        return (function (tx, data) {
            d.resolve(data)
        })
    };

    function failureWrapper(d) {
        return (function (tx, error) {
            d.reject(error)
        })
    };

    $.when(runQuery()).done(function (dta) {
        alert('Hello '   dta.rows.item(0).Name   '!');
    }).fail(function (err) {
        alert('An error has occured.');
        console.log(err);
    });

})()
  

Комментарии:

1. Хммм. Я бы подумал, что вы бы вызвали successWrapper (tx, data) вместо successWrapper (d). JavaScript сложен.

2. Проблема, с которой я столкнулся, заключалась в сохранении отложенного объекта в области видимости после вызова ExecuteSQL. Создав функцию, которая возвращает функцию, я достиг этой цели.

Ответ №2:

Наткнулся на этот вопрос, когда искал что-то еще, но я думаю, что у меня есть некоторый шаблонный код, который поможет вам начать обертывание запросов WebSQL в jQuery Promises.

Это пример, sqlProviderBase для $.extend использования вашим собственным провайдером. У меня есть пример с taskProvider и страницей, которая вызывала бы событие taskProvider on the page show. Это довольно редко, но я надеюсь, что это поможет указать другим правильное направление для обертывания запросов в promise для лучшей обработки.

 var sqlProviderBase = {

    _executeSql: function (sql, parms) {

        parms = parms || [];

        var def = new $.Deferred();

        // TODO: Write your own getDb(), see http://www.html5rocks.com/en/tutorials/webdatabase/todo/
        var db = getDb();

        db.transaction(function (tx) {
            tx.executeSql(sql, parms,
            // On Success
            function (itx, results) {
                // Resolve with the results and the transaction.
                def.resolve(results, itx);
            },
            // On Error
            function (etx, err) {
                // Reject with the error and the transaction.
                def.reject(err, etx);
            });
        });

        return def.promise();
    }
};

var taskProvider = $.extend({}, sqlProviderBase, {

    getAllTasks: function() {

        return this._executeQuery("select * from Tasks");

    }

});

var pageThatGetsTasks = {
    show: function() {

        taskProvider.getAllTasks()
                    .then(function(tasksResult) {

                        for(var i = 0; i < tasksResult.rows.length; i  ) {
                            var task = tasksResult.rows.item(i);

                            // TODO: Do some crazy stuff with the task...
                            renderTask(task.Id, task.Description, task.IsComplete);

                        }

                    }, function(err, etx) {

                        alert("Show me your error'd face: ;-[ ");

                    });

    }
};
  

Комментарии:

1. Спасибо, Джейкоб! tutsplus.com/lesson/deferreds/?WT.mc_id=learnjquery также говорится об отсрочках. Я смотрю на ваш код, и он соответствует тому, что говорит Джеффри Уэй.

Ответ №3:

Я ждал ответа, но пока ничего, поэтому я попробую. Я не могу запустить это, поэтому приношу извинения за любые ошибки.

Вы ищете что-то вроде:

 function deferredTransaction(db,transaction,transactionFunction(transaction)) {
    me=this;
    return $.Deferred(function(deferedObject){
        db.transaction(transactionFunction(transaction),
        function(tx,rs) { me.resolve(tx,rs); },
        function(tx,err) { me.reject(tx,err); } );
    }).promise();
}

dtx=deferredTransaction(db,tx,function(tx) {    
    tx.executeSql('SELECT * FROM MyTable WHERE CategoryField = ?', 
    [ selectedCategory ]);
dtx.then(function (tx, rs) { displayMyResult(rs); }, 
    function (tx, err) { displayMyError(err); } );
  

Ответ №4:

Я обнаружил, что обертывание отложенной транзакции в функцию и возврат обещания создает чистую и повторно используемую реализацию шаблона deferred / promise.

 var selectCategory = function() {
    var $d = $.Deferred();

    db.transaction(
        function(tx) {
            tx.executeSql(
                "SELECT * FROM MyTable WHERE CategoryField = ?"
                , [selectedCategory]
                , success
                , error
            )
        }
    );

    function success(tx, rs) {
        $d.resolve(rs);
    }

    function error(tx, error) {
        $d.reject(error);
    }

    return $d.promise();
};

selectCategory()
    .done(function(rs){
        displayMyResult(rs);
    })
    .fail(function(err){
        displayMyError(err);
    });