WildDogTeam / wilddog-issue

关于野狗产品的问题,bug反馈和改进意见
2 stars 1 forks source link

如何实现自增字段? #50

Closed SinanWang closed 8 years ago

SinanWang commented 8 years ago

要实现类似SQL中自增的字段,可以使用transaction API。

 // 先使用transaction()方法把counter计数器加1,transaction可以解决多端并发+1问题。
 ref.child('counter').transaction(function(currentValue) {     var newValue = (currentValue||0) + 1;     return newValue;
 }, function(err, committed, ss) {     if( err ) {
        setError(err);
     }     else if( committed ) {        // 如果counter加1成功,那么写入数据。
        var id = ss.val();  // 这里可以拿到自增后的id
        addRecord(id); 
     }
 });

transaction() 方法接受2个回调函数作为参数。第一个函数将会获取到当前的值,return的是即将被写入的值。这里我们对counter进行+1操作。第二个回调函数中的committed为true时,代表这个transaction已经成功,此时我们push一条新的记录。

transaction()的原理是,在向云端写入newValue的时候,会判断云端的数据仍然是旧的currentValue。如果云端数据已被其他客户端修改掉了,那么这次请求就会失败并重试。重试的过程是,重新从云端获取数据的值,记为currentValue,重新计算新值(+1),重新向云端写入。这个过程一直重复直至写入成功,或者超过最大重试次数。这些工作都是野狗SDK内部完成了的,我们无需关心其原理,只要根据文档,知道API的用法就可以了。

关于transaction()的文档,请参考https://z.wilddog.com/web/api#transaction-0

yangyongliang commented 8 years ago

实现分页请参考 :https://wilddog.kf5.com/hc/kb/article/188871/

如果数据集不是静态的,而是不断在插入和删除的,那么分页中页码的定义会变的很麻烦。

如果数据是只写入而没有删除操作,那么分页的实现比较简单,主要有两种方法:

使用priority作为页码

在写入数据的时候,使用priority做为数据的页码。

// 读取第2页数据new Wilddog("https://examples-sql-queries.wilddogio.com/messages") .orderByPriority() .startAt(2) // .endAt(2) .once('value', function(snap) { console.log('messages :', snap.val()); }); 为数据生成自增字段

参考自增字段。 假设我们为列表数据中的每一条记录都生成了一个自增的字段,就可以计算其页码了。

var startId = (pageNo - 1) * pageSize + 1;var endId = startId + pageSize;new Wilddog("https://examples-sql-queries.wilddogio.com/messages") .orderByChild('id') .startAt(startId) // .endAt(endId) .once('value', function(snap) { console.log('messages :', snap.val()); }); 依靠上一页的最后一条记录获取下一页数据

如果数据不是append only的,最好的做法是标记上一页取到的最后一条数据,从这一页开始取(适用于上拉加载数据)。

// 加载下一页数据new Wilddog("https://examples-sql-queries.wilddogio.com/pagination") .startAt(null, lastKeyOnPrevPage) .limitToFirst(LIMIT+1) // 多取一条,因为上一页的最后一条记录会被取出来,需要排除掉 .once('value', function(snap) { var vals = snap.val()||{}; delete vals[lastKeyOnPrevPage]; // 排除上一页最后一条记录 console.log('on this page', vals); });