简体   繁体   English

将基于JavaScript原型的对象保存在sessionStorage中?

[英]Save JavaScript prototype based objects in sessionStorage?

var obj = { 
conn : null,
first : function(thisIdentity) {
    "use strict";
    var myObj = this;
    $(document).on('click', thisIdentity, function(e) {
    e.preventDefault();
    $.ajax ({ 
        url : some value,
        // other parameters
        success : function(data) {
            myObj.conn = new Connection(data.user_id, "127.0.0.1:80");
            sessionStorage.setItem('connection', JSON.stringify(myObj.conn));
           }
        });
   },
second : function(thisIdentity) {
    "use strict";
    var myObj = this;
    var conntn = sessionStorage.getItem('connection');
        $(document).on('click', thisIdentity, function(e) {
        e.preventDefault();
        $.ajax ({ 
            url : some value,
            // other parameters
            success : function(data) { 
            var parsedConnection = JSON.parse(conntn);
            parsedConnection.sendMsg(data.id, data.nid);
        }
      });
    }
};
var Connection = (function() {
    function Connection(uid, url) {
       this.uid = uid;
       this.open = false;
       this.socket = new WebSocket("ws://"+url);
       this.setupConnectionEvents();
    },
Connection.prototype = {
    sendMsg : function(id, nid) {
        alert("Working");
    },
    // other functions
    }
})();

So connection is made in the AJAX callback function of first and I store the object in the sessionStorage via JSON but when I use it in the AJAX callback of second then error is coming that 因此,连接是在第一个的AJAX回调函数中进行的,我通过JSON将对象存储在sessionStorage ,但是当我在第二个的AJAX回调中使用该对象时,就会出现错误

TypeError: parsedConnection.sendMsg is not a function TypeError:parsedConnection.sendMsg不是函数

Now I understand that may be it is because JSON can be used to store plain objects not prototype-based objects . 现在我知道这可能是因为JSON可用于存储普通对象而不是基于原型的对象

My question is : Can any one tell me how to store prototype-based objects via JSON or any other way to implement this? 我的问题是: 谁能告诉我如何通过JSON或任何其他方式存储基于原型的对象?

I don't want to use eval . 我不想使用eval Any code, reference would be much appreciated. 任何代码,参考将不胜感激。 Thanks! 谢谢!

UPDATE 更新

I did as @Dan Prince mentioned but then a new problem occurred that now when in sendMsg function I use 我像@Dan Prince提到的那样做,但是出现了一个新问题,现在在sendMsg函数中使用

this.socket.send(JSON.stringify({
   action: 'message',
   rec: receiver,
   msg: message
}));

Then it stays 然后它留下来

InvalidStateError: An attempt was made to use an object that is not, or is no longer, usable InvalidStateError:尝试使用一个不可用或不再可用的对象

Any inputs? 有输入吗? Thanks! 谢谢!

You could probably hack your own solution into place by storing the prototype as a property of the object, then reinstantiating it with Object.create after you read it, but the real question is why do you want to do this in the first place? 您可以通过将原型存储为对象的属性,然后在读取对象后使用Object.create对其进行实例化,从而破解自己的解决方案,但是真正的问题是为什么首先要这样做?

I would suggest writing a serialize method on Connection 's prototype, which exposes only the essential information (there's no sense serializing a web socket for example). 我建议在Connection的原型上编写一个序列化方法,该方法仅公开基本信息(例如,对Web套接字进行序列化是没有意义的)。

Connection.prototype.toJSON = function() {
  return JSON.stringify({
    uid: this.uid,
    url: this.url,
    open: this.open
  });
};

Then use this method when you save the connection object into session storage. 将连接对象保存到会话存储时,请使用此方法。

myObj.conn = new Connection(data.user_id, "127.0.0.1:80");
sessionStorage.setItem('connection', myObj.conn.toJSON());

Each saved connection now has the minimum amount of data you need to call the constructor and recreate the instance. 现在,每个保存的连接都具有调用构造函数和重新创建实例所需的最少数据量。

When you load a connection from session storage, parse it and pass the values back into the constructor. 从会话存储中加载连接时,请对其进行解析,然后将值传递回构造函数。

var json = sessionStorage.getItem('connection');
var data = JSON.parse(json);
var connection = new Connection(data.uid, data.url)

// ...
connection.sendMsg(data.id, data.nid);

This will recreate the correct prototype chain in a natural and predictable way. 这将以自然和可预测的方式重建正确的原型链。

It's hard to see exactly what you are trying to achieve in every respect, but let's assume : 很难确切地看到您在各个方面想要实现的目标,但让我们假设:

  • for various DOM elements, a click handler (delegated to document) will cause asynchronously derived data to be sent via socket.send(). 对于各种DOM元素,单击处理程序(授权给文档)将导致通过socket.send()发送异步派生的数据。
  • the socket is to be initialized with an asynchronously derived uri. 套接字将使用异步派生的uri进行初始化。
  • the socket is to be kept available for immediate reuse. 套接字应保持可供立即使用。
  • data by which the socket is initialized is to be cached in local storage for future sessions. 初始化套接字所用的数据将缓存在本地存储中,以供将来的会话使用。 (It makes no sense to store the socket itself). (存储套接字本身没有任何意义)。

In addition, we need to acknowledge that a socket consume resources should really be disposed of if its resuse is not immediate. 另外,我们需要承认,如果套接字重新使用不是立即进行的,则应该真正处理它消耗的资源。

The whole strategy is abnormally complex. 整个策略异常复杂。 The overhead of performing an ajax operation once per session to obtain a uri would typically be accepted, as would the creation of a socket each time one is needed. 每个会话执行一次ajax操作以获得uri的开销通常会被接受,就像每次需要一个套接字时创建套接字一样。 However, it's an intersting exercise to write something with all the stated characteristics. 但是,写具有所有规定特征的东西是一个有趣的练习。

This may not be 100% correct but could possibly give you some ideas, including the use of promises to cater for several asynchronisms. 这可能不是100%正确的,但可能会给您一些想法,包括使用promises来解决一些异步问题。 Here goes ... 开始 ...

var obj = {
    conn: null,
    init: function(thisIdentity) {
        // It makes sense to attach the click handler only *once*, so let's assume this is an init function.
        "use strict";
        var myObj = this;
        $(document).on('click', thisIdentity, function(e) {
            e.preventDefault();
            $.ajax ({
                url : some value,
                // other parameters
            }).then(function(data) {
                myObj.send(JSON.stringify({
                    'id': data.id,
                    'nid': data.nid
                }));
            });
        });
    },
    send: function(data) {
        "use strict";
        var myObj = this;
        return myObj.getSocket().then(function(socket) {
            socket.send(data);
        }).then(function() {
            // by disposing in later event turn, a rapid series of send()s has at least a chance of using the same socket instance before it is closed.
            if(socket.bufferedAmount == 0) { // if the socket's send buffer is empty, then dispose of it.
                socket.close();
                myObj.conn = null;
            }
        });
    },
    getSocket: function() {
        "use strict";
        var myObj = this;
        //1. Test whether or not myObj.conn already exists ....
        if(!myObj.conn) {
            //2 .... if not, try to recreate from data stored in local storage ...
            var connectionData = sessionStorage.getItem('connectionData');
            if(connectionData) {
                myObj.conn = myObj.makeSocket(connectionData.user_id);
            } else {
                //3. ... if connectionData is null, perform ajax.
                myObj.conn = $.ajax({
                    url: some value,
                    // other parameters
                }).then(function(data) {
                    sessionStorage.setItem('connectionData', JSON.stringify(data));
                    return myObj.makeSocket(data.user_id);
                });
            }
        }
        return myObj.conn; // note: myObj.conn is a *promise* of a socket, not a socket.
    },
    makeSocket: function(uid) {
        "use strict";
        var myObj = this;
        var uri = "127.0.0.1:80"; // if this is invariant, it can be hard-coded here.

        // return a *promise* of a socket, that will be resolved when the socket's readystate becomes OPEN.
        return $.Deferred(function(dfrd) {
            var socket = new WebSocket("ws://" + uri);
            socket.uid = uid;
            socket.onopen = function() {
                myObj.setupConnectionEvents();// not too sure about this as we don't know what it does.
                dfrd.resolve(socket);
            };
        }).promise();
    }
};

Under this scheme, the click handler or anything else can call obj.send() without needing to worry about the state of the socket. 在这种方案下,单击处理程序或其他任何东西都可以调用obj.send()而不必担心套接字的状态。 obj.send() will create a socket if necessary. 如有必要, obj.send()将创建一个套接字。

If you were to drop the requirement for storing data between sessions, then .send() and .getSocket() would simplify to the extent that you would probably choose to roll what remains of .getSocket() into .send() . 如果您放弃在会话之间存储数据的要求,那么.send().getSocket()会简化到您可能选择将.getSocket()剩余内容.getSocket().send()

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM