如何在同步方法

时间:2015-08-14 12:44:54

标签: javascript html5 asynchronous web synchronous

我开发了一种用于将数据存储在LocalStorage中的Web技术游戏。 LocalStorage用作synchronous.To设置并从localstorage获取值

//设置localstorage中的值

localStorage.setItem('Key', "value");

//从localstorage

获取值
var localValue = localStorage.getItem('Key');

localstorage有5MB的限制。在发挥一定程度后,本地存储完全填满。我需要在客户端进行大面积存储。

我的第一个问题是“解决这个问题的最佳方法是什么?”

为了解决上述问题,我找到了LargeLocalStorage。它是异步的。

//在LargeLocalStorage中设置值

storage.setContents('docKey', "the contents...").then(function() {alert('doc created/updated');});

//从LargeLocalStorage获取值

storage.getContents('myDoc').then(function(content){//content is value for particular key});

是否有任何方法可以使这些方法同步,因为我的所有代码都是根据同步localstorage。根据异步LargeLocalStorage更改整个逻辑需要花费大量时间。

我目前正尝试将localstorage的setItem和getItem方法覆盖为:

localStorage.__proto__.getItem = function(key) {

var returnVal;

storage.getContents(key).then(function(content) {
        returnVal = content;

    });
return returnVal;//it returns undefined
}

由于异步行为,上面覆盖方法返回未定义的值。

请使用上述方法帮助我获得价值同步。

提前致谢。

2 个答案:

答案 0 :(得分:0)

好的,LocalStorage很安静,但是如果你想存储大量数据,我建议你看看 PouchDB ,这是 CouchDB ,一个NoSQL数据库。

Pouchdb使用 IndexedDB 作为其存储机制。因此,PouchDB在浏览器中运行,提供了速度。

我认为这对您的情况非常有帮助:)。

如果你有时间看一下我所做的这段代码:

数据库类

var Database = (function(){

    var instance = undefined;

    function Database(){
      //Create new database Game
      this.db = new PouchDB('Game');

      //Listen for db changes, and fired show function
      this.db.changes({
        since: 'now',
        live: true
      }).on('change', this.show);

    }

    //Show function retrieve all docs, and add it to the html
    Database.prototype.show = function(){
      this.db
      .allDocs({include_docs: true, descending: true})
      .then(function(response){
        var data = response.rows;
        var preview = document.querySelector('.preview');
        while (preview.firstChild) {
            preview.removeChild(preview.firstChild);
        }
        data.forEach(function(elm){
          var p = document.createElement('p');
          p.innerHTML = elm.doc.title;
          preview.appendChild(p);
        });
      });
    }


    //Add a doc to our database
    Database.prototype.add = function(data){
      this.db
      .post(data)
      .then(function(response){
        console.log('Data added !');
      }).catch(function(err){
        console.log(err);
      });
    }

    //Clean our database
    Database.prototype.reset = function(){
      var db = this.db;
      //retrieve all docs
      db.allDocs({include_docs:true, descending: true})
        .then(function(response){
          var rows = response.rows;
          var docs = rows.map(function(elm){
            return elm.doc;
          });
          //Create promises array
          var promises = docs.map(function(elm){
            //Return promise remove
            return db.remove(elm._id, elm._rev);
          });
          //Resolve all promisein our array
          Promise.all(promises).then(function(data){
            console.log('Database Cleaned !');
          });
        });
    }

    return {
      get: function(){
        if (!instance){
          instance = new Database();
        }
        return instance;
      }
    }

  })();

采取一些行动

  //Create a database
  var DB = Database.get();

  function add(){
    var value = document.querySelector('#value').value;

    var obj = {
      title: value
    };
    //Add obj to our database
    DB.add(obj);
  }

  function reset(){
    //Reset our database
    DB.reset();
  }

<强> HTML

<input type="text" name="name" id="value">
<button type="button" name="button" onclick="add()">add</button>
<button type="button" name="button" onclick="reset()">Destory database</button>
<div class="preview">
</div>

我认为 PouchDB 是一个非常好的东西,如果你有时间,可以自由测试它:)

答案 1 :(得分:0)

  

是否有任何方法可以使这些方法同步

没有。异步方法是异步的,因为它们是异步的。你不能在明天(或从现在起100ms)发生一些事情,而不是现在发生。

你真正想要的是一种编写异步代码的方法,使它看起来像同步代码。这将更具可读性,在您的情况下,将使您的代码更容易适应。

我们想以某种方式写出

A() . then(B);

as

A();
B();

并且意思相同:在执行B之前等待A完成。如果涉及变量或结果,那么我们希望能够写

A() . then(function(a) { return B(a+1); })

作为

var a = A();
B(a+1);

异步功能

事实证明的一种方法:异步函数。此功能绝不适用于所有环境,但很容易找到访问它的方法。要使用异步功能,我将关键字async放在function前面,然后使用特殊关键字await。所以上面的代码只是:

async function foo() {
  var a = await A();
  await B(a+1);
}

要使其工作,请使用Babel转换代码,选择启用异步功能的选项。 Babel会将您的代码翻译成ES5,这是所有浏览器都知道如何解释的JavaScript。

上面的代码实际上会返回一个承诺,你可以挂起then,或者在另一个异步函数中使用:

async function bar() {
  await foo();
}

在您的具体案例中:

async function write(contents) {
  await storage.setContents('docKey', contents);
  alert('doc created/updated');
}

发电机

您可能想了解另一种方法。它使用“生成器”,它是ES6中一种特殊类型的函数,它“返回”一个值,但保持它们的状态,并且可以再次调用并在之间执行之后返回更多值。生成器是这样写的,在函数名后面加*

function* foo() {
  yield 1;
  yield 2;
}

以特殊方式调用此函数。首先,将其称为foo()以创建一个名为 iterator 的东西,然后使用迭代器的next方法获取下一个值。 (还有其他方法可以检索值序列,我们不会在这里讨论。)

这些生成器可用于编写所需的“异步但看起来同步”的代码,如下所示:

function* foo() {
  var a = yield A();
  yield B(a+1);
}

代码看起来与异步函数非常相似,但yield替换await

但在这种情况下,与上述异步函数不同,我们需要某人或某事要求第一个值,然后等待yield返回的承诺解析,然后要求第二个值,并且等等。这样做的代码不长,但有点复杂。有许多库和实用程序正是这样做的。例如,一个众所周知的名为co。使用co,您可以编写与我之前显示的异步函数相同的代码,如下所示:

var foo = co.wrap(function* foo() {
  var a = yield A();
  yield B(a+1);
});

采用这种方法的一个原因是发电机是ES6的标准配置,并且比异步功能更广泛可用,这些功能正在考虑用于ES7。