2014-02-14 3 views
0

У меня есть серверный сервер с REST api. В интерфейсе я использую Angular.js. Чтобы обрабатывать часть в реальном времени, я хотел бы использовать стороннюю службу, такую ​​как Pusher.Javascript библиотека для реального времени и оффлайн веб-приложение

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

Например, с угловой стороны я хотел бы подписаться на мою модель и получать уведомления о ее изменении. Я также хотел бы иметь метод .save(), который будет обрабатывать синхронизацию с сервером и другими клиентами.

Эта библиотека должна:

  • Работа в автономном режиме: он будет сохранять данные в local_storage и синхронизироваться с сервером, когда он получает обратно в оперативный режим.

  • Слушайте изменения в реальном времени, обновите свою модель и передайте изменения слушателям.

  • Хорошо работать со стандартным интерфейсом REST.

Так же, как быстрый псевдокод, например, в Угловом я хотел бы сделать:

my_controller = function($scope) { 
    User.find_all(function(users) { 
    $scope.users = users; 
    }); 
} 

Пользователь модели абстракция .. когда он получает обновления в режиме реального времени, мой $ объем . Пользователи должны соответственно измениться.

$scope.users[0].set('name', 'testing) 

Это должно сохранить модель на сервере. Или в автономном режиме следует сохранять его локально и синхронизировать его позже, когда он снова подключен к сети.

Я знаю, что есть интернет-услуги, пытающиеся это сделать, например, Firebase и kinvey. Проблема с этими инструментами заключается в том, что она предлагает только размещенное решение. Мне нужно контролировать сервер REST и базу данных. Итак, в основном, я ищу библиотеку «Firebase» - без всех аутентификаций и авторизаций, которые могли бы работать с сервером REST и третьей стороной pubsub.

Спасибо!

ответ

-1

Я думаю, вы должны начать изучение HTML5 WebSockets: http://www.websocket.org/

Это позволяет двунаправленную связь между сервером и клиентом, клиентом и сервером тянуть толчок.

Тогда посмотрите на SignalR, реализация asp.net в HTML5 WebSockets: http://www.asp.net/signalr

1

это немного долго ответа, но я не опубликовать его еще.

function monitor(obj, callBack){ 


var api={ 
     patch: patchObjectWithDiff, 
     init: init, 
     resolve: resolve, 
     snapshot: snapshot, 
     diff: diff, 
     update: changeMonitor 
    }; 



function merge2(o, ob) { 
    for (var z in ob) { 
     if (ob.hasOwnProperty(z)) { 
      if(typeof ob[z]=="object"){ 
       if(ob[z]==null){ 
        delete o[z]; 
       }else{ 
        merge2(o[z] || {}, ob[z]); 
       } 

      }else{ 
       o[z] = ob[z]; 
      } 

     } 
    } 
    return o; 
} 






function snapshot(obj) { 
    var out = []; 
    function merge3(ob, path) { 
     path = path || []; 
       var tp; 
     for(var z in ob) { 
      if(ob.hasOwnProperty(z)) { 
       if(ob[z] && typeof ob[z] == "object" && [Date, RegExp].indexOf(ob[z].constructor) == -1) { 

             tp=path.concat(z); 
        out.push({ 
               path: tp.join("`"), 
               path2: tp, 
               dt: "set", 
               date: +new Date, 
               v: Array.isArray(ob[z]) ? "[]" : "{}" 
             }); 

        merge3(ob[z], path.concat(z)); 
       } else { 
             tp=path.concat(z); 
        out.push({ 
               path: tp.join("`"), 
               path2: tp, 
               type: "set", 
               dt: +new Date, 
               v: JSON.stringify(ob[z]) 
             }); 
       } 
      } 
     } 
    } 

    merge3(obj); 
    return out; 
}; 



function diff(d1, d2){ 

    var out=d2.filter(function(a,b,c){ 
    var ov=JSON.stringify(a.v); 
    return d1.some(function(aa,bb){ return aa.path==a.path && JSON.stringify(aa.v) != ov; }); 
    }), 

    // find deletions 
    dels=d1.filter(function(a,b,c){ 
    return !d2.some(function(aa,bb){ if(aa.path==a.path){ return true; }; }); 
    }), 

    allPaths=dels.map(function(a){return a.path}).sort(), 

    dels2=dels.filter(function eliminateUnneededSubBranches(a){ 

     var pos=allPaths.indexOf(a.path2.slice(0,-1).join("`")); 

     return pos==-1 || pos >= allPaths.indexOf(a.path); 

    }).map(function(a){a.type="del"; delete a.v; return a;}); 


    [].push.apply(out, dels2); 


//find inserts 


var outNew=d2.filter(function(a,b,c){ 
    var ov=JSON.stringify(a.v); 
    return !d1.some(function(aa,bb){ return aa.path==a.path }); 
    }); 

[].push.apply(out, outNew); 



    return out.map(function(a){ 
     var x= { 
     dt: a.dt, 
     k: a.path2 
     }; 

     if(a.hasOwnProperty("v")){ x.v=a.v; } 

     return x; 

      a.k=a.path2; 
      delete a.path; 
      delete a.path2; 
      delete a.type; 
     return a; 
    }); 
} 



function resolve(path, object){ 
    var tob=object; 
    path.map(function(a){ return (tob=tob[a])||tob; }) 
return tob; 
} 








function patchObjectWithDiff(diff, object){ 

    diff.forEach(function(a,b,c){ 
     var p= resolve(a.k.slice(0,-1), object), 
      k= a.k.slice(-1)[0]; 

     if(a.hasOwnProperty("v")){ //set: 
       p[k]=JSON.parse(a.v); 
      if(String(p[k]).match(/Z$/)){ p[k]=new Date(''+p[k]) || p[k]; } 
     }else{ // del: 
      if(Array.isArray(p)){ p.splice(k,1); }else{ delete p[k]; } 
     } 
    }); 

    return object; 
} 











    var init=snapshot(JSON.parse(JSON.stringify(obj))), 
      id=Math.random()+ Number(new Date()); 


    var init=snapshot(obj); 

    function changeMonitor(){ 
     var thisTime=snapshot(obj), 
       diffs=diff(init, thisTime); 
     if(diffs.length){ 
      api.diffs=diffs; 
      (callBack||console.log.bind(console))("objectUpdate", diffs); 
      init=thisTime; 
     }//end if change? 
    } 

    setInterval(changeMonitor, 2500); 

return api; 

} 

демо/пример использования:

var obj={a:1, b:[1,2,3], c: false}; // a model object 
var dupe=JSON.parse(JSON.stringify(obj)); // a cheap clone of the data for demo use 

//subscribe this object to updates  
var mon=monitor(obj, function(type, changes){console.log(type, changes); }); 

// make some changes to the object: 
obj.e="cool!"; 
obj.b.push(5); 
obj.a=7; 

// manually call update instead of waiting for the bundler: 
// (this is needed for this demo so we can reconcile the changes in sync and view the output) 
mon.update(); 

// now apply stored changes to the clone of the orig data: 
var updatedDupe= mon.patch(mon.diffs, dupe); 

// use a cheap and easy but not production-reliable to compare the objects: 
JSON.stringify(updatedDupe)==JSON.stringify(obj); // should be true 

испытаны в хром и Firefox.

Помните, что использование данного JOON конкретного демонстрационного примера зависит от некоторой удачи и последовательного заказа клавиш, что не гарантируется спецификацией JS. Порядок клавиш не имеет большого значения, но это может привести к сбою сравнения JSON.stringify() ==, хотя свойства объекта действительно синхронизированы. Это просто для демонстрации, чтобы получить истинный/ложный ответ, если он работает, не бить меня ...

вы можете дать ему специальный обратный вызов для отправки («diff», }) изменения по мере их возникновения, а затем использовать подписанное событие из pusher et al. («diff», function (e) {mon.patch (e.diffs, obj);}); применить ваши изменения и запустить обновление просмотра в вашем MVC.

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

Все в файлах изменений списка изменений поставляются с тремя ключами:

{"dt":1392348959730,"k":["b","3"],"v":"5"} 
dt: a timestamp of when the change was discovered 
k: the key path where the change was detected 
v: what the discovered changed value is as of dt 

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

Смежные вопросы