javascript 如何使 WebSQL 查询同步?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/14798710/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-26 22:36:49  来源:igfitidea点击:

How to make a WebSQL query synchronous?

javascriptsqliteasynchronoussynchronousweb-sql

提问by user2058890

Consider:

考虑:

var globalvar;

function viewyearmain() {
  db.transaction(function (tx) 
  {
    tx.executeSql('SELECT * FROM BUDGET WHERE holdingtype="month"', [], function (tx, results) 
    {
       var len = results.rows.length;
       msg = len;
       globalvar = msg;
    }, null);

  });

  if (globalvar>0)
  {
    alert("ROWS FOUND");
  }
  else
  {
    alert("ROWS NOT FOUND");
  }
}

The problem is that ROWS NOT FOUNDappears because the transaction has not completed by the time the ifstatement is reached.

ROWS NOT FOUND出现问题是因为在if到达语句时事务尚未完成。

采纳答案by CL.

An asynchronous callback is not synchronous, regardless of how much you want it to be.

异步回调不是同步的,无论您希望它是多少。

Just move allthe code the depends on the result into the callback:

只需将依赖于结果的所有代码移动到回调中:

var globalvar;

function viewyearmain() {
  db.transaction(function (tx) 
  {
    tx.executeSql('SELECT * FROM BUDGET WHERE holdingtype="month"', [], function (tx, results) 
    {
       var len = results.rows.length;
       msg = len;
       globalvar = msg;
       if (globalvar>0)
       {
         alert("ROWS FOUND");
       }
       else
       {
         alert("ROWS NOT FOUND");
       }
    }, null);

  });
}

Alternatively, move it into a second function, and call that from the callback.

或者,将其移动到第二个函数中,并从回调中调用它。

回答by Kevin

I'm a couple of years late, but considering that the question was never directly answered, I figured I'd throw my two cents in, as well ass add some suggestions!

我迟到了几年,但考虑到这个问题从来没有直接回答过,我想我会投入我的两分钱,并添加一些建议!

First, if you're reading this, you probably shouldn't be using WebSQL. It has been deprecatedin favor of IndexedDB, which at this point is the only database on the W3C standards track.

首先,如果您正在阅读本文,您可能不应该使用 WebSQL。它已被弃用,取而代之的是 IndexedDB,它是 W3C 标准轨道上唯一的数据库。

If, for whatever reason, you're intent on using WebSQL, and you can live without the benefits that its asynchronous API offers (some of which are mentioned in John Fowler's answer), then you should know that its spec also defines a synchronous API.

如果出于某种原因,您打算使用 WebSQL,并且可以在没有其异步 API 提供的好处的情况下生活(其中一些在 John Fowler 的回答中提到),那么您应该知道它的规范还定义了一个同步 API.

So yes, there is a way to execute statements in WebSQL synchronously, provided the browsers you are developing for have implemented the synchronous API.

所以是的,有一种方法可以同步执行 WebSQL 中的语句,前提是您正在开发的浏览器已经实现了同步 API。

If you don't mind dealing with an asynchronous interface that is just about as simple as a synchronous one, check out BakedGoods.

如果您不介意处理与同步接口一样简单的异步接口,请查看BakedGoods

With it, executing your query is as simple as:

有了它,执行查询就像:

bakedGoods.getAll({
    filter: "valueObj.holdingType === 'month'",
    storageTypes: ["webSQL"],

    //Contains database configuration data and operation preferences
    options: optionsObj,

    complete: function(byStorageTypeResultDataObj, byStorageTypeErrorObj){}
});

Its simple interface and unmatched storage facility support comes at the cost of lack of support for some storage facility-specific configurations. For instance, it does not support the conduction of storage operations in WebSQL tables with multi-column primary keys.

其简单的界面和无与伦比的存储设施支持是以缺乏对某些存储设施特定配置的支持为代价的。例如,它不支持在具有多列主键的WebSQL 表中进行存储操作。

So if you make heavy use of those types of features, you may want to look elsewhere.

因此,如果您大量使用这些类型的功能,您可能想看看其他地方。

Oh, and for the sake of complete transparency, BakedGoods is maintained by yours truly :) .

哦,为了完全透明,BakedGoods 由您真正维护:)。

回答by DdD

Not quite synchronous - but it's a start.

不完全同步 - 但这是一个开始。

Create a helper function to execute your queries from within a Promise

创建一个辅助函数以从 Promise 中执行您的查询

const executeSql = (query, params) => new Promise ( (resolve, reject) => {
  tx.executeSql(query, params, resolve, reject);
};

Then when running from an async function, you can use the 'await' keyword

然后从异步函数运行时,您可以使用“await”关键字

const myFunc = async () => {
   let result = await executeSql("SELECT * FROM BUDGET WHERE holdingtype=?", ["month"]);
}

However you MAY have issues with the result of the transaction as the object may de-reference once the Promise fulfils.

但是,您可能会遇到事务结果的问题,因为一旦 Promise 实现,对象可能会取消引用。

const executeSql = (query, params) => new Promise ( (resolve, reject) => {
    tx.executeSql(query, params, 
        (tx, results) => {
            var items = [];
            if(results.rows.length)
            {
                var max = results.rows.length;
                for (var x = 0; x < max; x++) items.push(results.rows.item(x))
            }
            resolve(items)
        }, reject)
    })

回答by cilf

Nowadays, you can take advantage of async / awaitand promises like this:

如今,您可以利用async / await和承诺这样的:

async function alertResult() {
  const rows = await viewyearmain();
  if (rows.length) {
    alert("ROWS FOUND");
  } else {
    alert("ROWS NOT FOUND");
  }
}

function viewyearmain() {
  return new Promise(resolve => {
    db.transaction(function(tx) {
      tx.executeSql("SELECT * FROM BUDGET WHERE holdingtype = ?;", ["month"], function(tx, result) {
        resolve(result.rows);
      }, null);
    });
  });
}

回答by John Fowler

To my knowledge, WebSQL does not support synchronous SQL statements. This is normally a good thing, as you do not want the processing of SQL to disrupt or freeze your User Interface. As such, CL.'s answer provides the right asynchronous mechanism for processing results to a query.

据我所知,WebSQL 不支持同步 SQL 语句。这通常是一件好事,因为您不希望 SQL 处理中断或冻结您的用户界面。因此,CL. 的答案为处理查询结果提供了正确的异步机制。

If, however, you truly desire synchronous SQL queries, then check out the WebSQL alternative: SequelSphere - An HTML5 / JavaScript SQL Relational Database.

但是,如果您真的需要同步 SQL 查询,那么请查看 WebSQL 替代方案: SequelSphere - HTML5 / JavaScript SQL 关系数据库

It is 100% JavaScript, so it runs in any browser and on any platform. Plus, it stores its data in either IndexedDB or LocalStorage. It also contains many bells and whistles that WebSQL does not: JSON Integration, Change Trackers, User-Defined SQL Functions, SYNCHRONOUS SQL processing, etc. Since the WebSQL standard has been deprecated, I think this is an excellent alternative.

它是 100% JavaScript,因此可以在任何浏览器和任何平台上运行。此外,它将数据存储在 IndexedDB 或 LocalStorage 中。它还包含许多 WebSQL 没有的花里胡哨:JSON 集成、更改跟踪器、用户定义的 SQL 函数、同步 SQL 处理等。由于 WebSQL 标准已被弃用,我认为这是一个很好的替代方案。

Full Disclosure: I love WebSQL, but am married to SequelSphere.

完全披露:我喜欢 WebSQL,但已与 SequelSphere 结婚。

回答by Ian

It's a bit late now but for what it's worth...you can't make the calls synchronous but you can simplify your code by using a library such as Async. It might seem like overkill but if you need to perform 3 or 4 statements in a row it can make your code a lot easier to read.

现在有点晚了,但对于它的价值......您无法使调用同步,但您可以通过使用诸如Async 之类的库来简化您的代码。这可能看起来有点矫枉过正,但如果您需要连续执行 3 或 4 条语句,它可以使您的代码更易于阅读。

async.waterfall([
    function(callback){
        db.transaction(function (tx) {
            tx.executeSql('SELECT * FROM BUDGET WHERE holdingtype="month"', [], 
                function (tx, results) {
                    var len = results.rows.length;
                    callback(null, len)
                }, 
                function(){
                    callback("An error occurred when reading data");
                }
            }); 
       });
    },
    function(len, callback){
        // Now do something with the length.
        console.log("The length is: " + len);
    }
]);