网站内容更新方案(Ajax通过定时去询问服务器是否有数据更新,怎么办?)
优采云 发布时间: 2021-10-15 00:00网站内容更新方案(Ajax通过定时去询问服务器是否有数据更新,怎么办?)
Ajax定期向服务器请求数据更新,这似乎是一个通用的解决方案,比如1元xx品类的网站,因为抢购模式需要更新产品的剩余副本。比如获取服务器当前参与人数,获取最新购买次数,发送私信,好友消息,每类数据设置一个时间,如:1秒到数据库取数据。大多数请求的链接都是无效的,请求过多会导致浏览器无响应。
二、为什么不能将两者结合起来,选择一个折衷的方案?
客户端脚本需要一个可以通知我们服务器端有数据更新的程序,然后执行注册的程序到服务器端获取相应的数据。
我们只需要服务端通知提供这样的数据结构:
{
//用户消息更新时间
msg: '20141192003261234',
//网站购买记录更新时间
buy: '20141192003534567'
}
获取客户端的当前数据后,将其与当前浏览器中存储的用户消息更新时间进行比较。如果msg更新时间和服务器给出的时间完全一致,我们就不需要去服务器去获取用户的个人消息了。相反,服务器中的消息被更新,我们开始执行我们预定的程序来获取服务器和用户收到的消息。显示给用户,并设置当前消息的更新时间。
我们需要的就这么简单——我们需要一个通知程序来通知我们
三、 我们需要做什么,会遇到那些问题。
让服务器通知客户端程序数据更新显然不是很划算。我们上面讨论过,所以需要在客户端设置一个循环定时程序,从服务器获取注册类型(用户消息,网站交易次数、购买次数、剩余产品数量),通过数据类型的注册时间来决定是否执行我们注册的方法。
问题1:定时程序必须有条不紊的执行ajax方法(上一个ajax完成后才能发送第二个ajax),服务器取数据是一个耗时的操作。
Ajax 异步递归。
问题二:不是每个页面都需要知道数据的变化
在不同的页面注册不同的监控信息。
问题三:如何动态启动和停止定时程序,并保持程序只能运行一个定时实例。
设置互斥锁。
问题4:服务器如何保存这些数据的更新状态(public:卷,individual:用户消息)。
需要一个存储介质来存储对应类型信息的更新时间
问题5:如何从异常中恢复。确保定时程序可以正常运行。
尝试...抓住...$.ajaxerror。
四、代码实现
客户端计时程序:
//客户端*敏*感*词*对象
var listener = {
tid: 0,
keys: "",
//任务存储对象
taskType: {},
//注册一个任务
appendTaskType: function (key, type) {
if (typeof (type) == "function" && typeof (key) == "string" && /^[a-z0-9]+$/.test(key)) {
//添加一个任务
this.taskType[key] = {
//任务执行函数
fun: type,
//变化量
ts: ''
};
var a = [];
for (var k in this.taskType) { a.push(k); }
this.keys = a.join('.');
}
},
//开始运行*敏*感*词*
start: function () {
//如果定时器正在运行则返回
if (this.tid != 0)
return;
fn();
//私有定时执行方法
function fn() {
$.getJSON("/api/listener", { keys: listener.keys }, function (d) {
//获取定时器所有的注册类型
for (var key in listener.taskType) {
//获取注册类型对象
var O = listener.taskType[key];
//判断当前对象是否存在和当前的值是否和之前的变化值一样,是否真正执行
if (d[key] && d[key] != O.ts) {
//更改现有状态
O.ts = d[key];
//执行注册函数
O.fun(O);
}
}
//设置ID
listener.tid = setTimeout(fn, 1000);
})
}
},
//关闭*敏*感*词*
stop: function () {
//清除定时器
clearTimeout(this.tid);
//归零
this.tid = 0;
}
}
//注册对页面的*敏*感*词*
listener.appendTaskType("msg", function () {
$.getJSON("/api/getlist", { key: 'msg' }, function (data) {
var b = $("#msgList");
b.hide();
b.empty();
var html = '';
for (var i = 0; i < data.length; i++) {
html += "【" + data[i].user + "】说:" + data[i].msg + ""
}
b.html(html);
b.slideDown(300);
})
});
//注册对购买记录的*敏*感*词*
listener.appendTaskType("buy", function () {
$.getJSON("/api/getlist", { key: 'buy' }, function (data) {
var b = $("#buyList");
b.hide();
b.empty();
var html = '';
for (var i = 0; i < data.length; i++) {
html += "【" + data[i].user + "】购买了:" + data[i].msg + ""
}
b.html(html);
b.slideDown(300);
})
})
//开始执行*敏*感*词*任务
listener.start();
服务器代码:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Web;
using System.Web.Mvc;
namespace MvcApplication1.Controllers {
public class ApiController : Controller {
//
// GET: /Api/
///
/// 根据缓存Key获取当前缓存最后更新的标示
///
/// 缓存Key
/// 最后更新的时间
public string getlast(string cacheKey) {
List ls = HttpRuntime.Cache.Get(cacheKey) as List;
if (ls != null)
return ls.First().time;
return "0";
}
///
/// 服务器定时方法,这个方法是检测,数据有没有进行更新
///
///
public ContentResult Listener(string keys) {
if (string.IsNullOrWhiteSpace(keys))
return Content("{}");
System.Text.StringBuilder builder = new System.Text.StringBuilder("{");
//客户端需要知道用户信息是否变动
if (keys.Contains("msg")) {
builder.AppendFormat("\"msg\":\"{0}\",", getlast("msg"));
}
//客户端需要知道购买列表是否变动
if (keys.Contains("buy")) {
builder.AppendFormat("\"buy\":\"{0}\",", getlast("buy"));
}
//类推各种*敏*感*词*.......
//移除最后“,”
if (builder.Length > 1) {
builder.Remove(builder.Length - 1, 1);
}
builder.Append("}");
return Content(builder.ToString());
}
public ContentResult msg(data ms) {
InsertCache(ms, "msg");
return Content("ok");
}
public ContentResult buy(data buy) {
InsertCache(buy, "buy");
return Content("ok");
}
private void InsertCache(data d, string cacheKey) {
//使用时间设置最后更新量
d.time = DateTime.Now.ToString("yyyyMMddhhmmssffff");
//获取存储的值
List ls = HttpRuntime.Cache.Get(cacheKey) as List;
//判断是否为空
if (ls == null) {
ls = new List();
HttpRuntime.Cache.Insert(cacheKey, ls);
}
//添加到集合
ls.Insert(0, d);
//移除大于这个数
if (ls.Count > 10)
ls.RemoveRange(10, ls.Count - 10);
}
public JsonResult GetList(string key) {
if (string.IsNullOrEmpty(key))
return Json(null, JsonRequestBehavior.AllowGet);
return Json(HttpRuntime.Cache.Get(key) as List, JsonRequestBehavior.AllowGet);
}
public JsonResult GetCache() {
return Json(new {
p1 = HttpRuntime.Cache.EffectivePercentagePhysicalMemoryLimit,
p2 = HttpRuntime.Cache.EffectivePrivateBytesLimit
},
JsonRequestBehavior.AllowGet);
}
}
//定义一个数据存储介质
public class data {
public string user { get; set; }
public string msg { get; set; }
public string time { get; set; }
}
}
请下载DEMO 点击下载