这可能是一个天真的问题,对不起,但我正在尝试解决潜在的并发问题。我有一个注册程序,从用户从下拉菜单中选择他们的类别开始。这会触发对Google工作表中特定页面的查询,在该页面中,它会检索显示给用户的可用ID号。在按下最终提交按钮之前,需要几个步骤。这(我认为)为不止一个人创造了检索相同ID的机会。我确实使用google的lockservice,但使用了将表单信息写入我的电子表格的功能(基于Martin Hawksley的脚本)。如果可以确定当前正在查看注册页面的人数,我可以使用if语句在查询中使用该值,以便检索不同的行号。这样可以消除重复的可能性。
听起来合理吗?也许有更好的方法。
任何建议都会受到最高的赞赏。
答案 0 :(得分:0)
如果可以确定当前正在查看的人数 注册页面
如果您不想使用Google Analytics。下面是一个简单示例,说明如何使用客户端轮询来维护会话,并计算有多少用户处于活动状态。
注意:我把它放在一起,它可能会被重构一点比较漂亮,但它应该得到它的要点
Working Example打开这几次,您会看到每个会话ID和一个计数。会话在没有活动60秒后过期,如果您关闭页面则会自动结束。
项目文件结构:
应用脚本
var sessionTimeout = 60; //60 seconds
//Triggered when the page is navigated to, serves up HTML
function doGet(){
var template = HtmlService.createTemplateFromFile('index');
template.userID = NewSession();
return template.evaluate()
.setTitle('Active Users')
.setSandboxMode(HtmlService.SandboxMode.IFRAME);
}
/*================ Polling ================*/
//Client calls this function to poll, updates cache, returns active users
function ClientPoll(id){
var scriptCache = CacheService.getScriptCache();
UpdateScriptCache(id, 0, scriptCache, true);
var activeIDs = GetActiveIDs(scriptCache);
return activeIDs;
}
function EndSession(id){
var scriptCache = CacheService.getScriptCache();
scriptCache.remove(id);
var activeIDs = GetActiveIDs(scriptCache);
activeIDs.splice(activeIDs.indexOf(id), 1);
UpdateScriptCache('ActiveIDs', activeIDs, scriptCache, false);
}
//Server calls every minute to check for inactive sessions
function CheckForInactiveSessions(){
var scriptCache = CacheService.getScriptCache();
var activeIDs = GetActiveIDs(scriptCache);
var allSessions = scriptCache.getAll(activeIDs);
if(Object.keys(allSessions).length > 0){
var keys = Object.keys(allSessions);
var newActiveIDs = [];
for(var i = 0; i < keys.length; i++){
newActiveIDs.push(keys[i]);
}
Logger.log(keys.length);
UpdateScriptCache('ActiveIDs', newActiveIDs, scriptCache, false);
}
}
/*================ Session Creation & Cache ================*/
//Handles setting up a new session, called when page is opened
function NewSession(){
var id = GenerateUID();
AddNewActiveID(id);
return id;
}
//Gets a list of all active IDs
function GetActiveIDs(scriptCache){
if(!scriptCache){
scriptCache = CacheService.getScriptCache();
}
var active = scriptCache.get('ActiveIDs');
if(active !== null){
return JSON.parse(active);
}
return [];
}
//Adds a new ID to the cache
function AddNewActiveID(id){
var scriptCache = CacheService.getScriptCache();
var activeIDs = JSON.parse(scriptCache.get('ActiveIDs'));
if(activeIDs == null){
activeIDs = [];
}
activeIDs.push(id);
//Update the Active ID List
UpdateScriptCache('ActiveIDs', activeIDs, scriptCache, false);
//Add new ID to cache
UpdateScriptCache(id, 0, scriptCache, true);
}
//Handles updating the Active IDs cache and prevents race conditions or collisions
function UpdateScriptCache(key, data, cache, timeout){
var lock = LockService.getScriptLock();
lock.waitLock(15000);
if(timeout){
cache.put(key, JSON.stringify(data), sessionTimeout);
} else {
cache.put(key, JSON.stringify(data), 21600)
}
lock.releaseLock();
}
/*================ ID Generation ================*/
//Handles generating and returning a new ID
function GenerateUID(){
var generator = new IDGenerator();
var id = generator.generate();
return id;
}
//Generates a random(ish) ID;
function IDGenerator() {
this.length = 10;
this.timestamp = new Date().getTime();
var getRandomInt = function( min, max ) {
return Math.floor( Math.random() * ( max - min + 1 ) ) + min;
}
this.generate = function(){
var timestamp = this.timestamp.toString();
var parts = timestamp.split('').reverse();
var id = '';
for(var i = 0; i < this.length; i++){
var index = getRandomInt(0, parts.length - 1);
id += parts[index];
}
return id;
}
}
<强> JavaScript的:强>
<script>
//Initilization
$(function(){
//Set the users ID in HTML
$('#userID').text(userID);
//Setup handler to end the session before the page closes
$(window).bind('beforeunload', function(){
EndSession();
});
//Start the timer
var deadline = new Date(Date.parse(new Date()) + 5000);
initializeTimer('pollingIn', deadline);
});
//Polls the server to update session and get active users
function PollServer(){
console.log('Polling server');
google.script.run.withSuccessHandler(UpdateActiveUsers).ClientPoll(userID);
var deadline = new Date(Date.parse(new Date()) + 5000);
initializeTimer('pollingIn', deadline);
}
//Ends the session right before the page closes
function EndSession(){
google.script.run.withSuccessHandler().EndSession(userID);
}
//Updates the active users div
function UpdateActiveUsers(users){
console.log(users)
var userText = '';
for(var i = 0; i < users.length; i++){
if(i == 0){
userText += users[i];
continue;
}
userText += ', ' + users[i];
}
$('#activeUsersCount').text(users.length);
$('#activeUsers').text(userText);
}
//Initilizes the timer
function initializeTimer(id, endtime) {
var timer = $('#'+id);
function updateTimer() {
var time = Date.parse(endtime) - Date.parse(new Date());
var seconds = Math.floor((time / 1000) % 60);
timer.text(seconds);
if (time <= 0) {
clearInterval(timeInterval);
PollServer();
}
}
updateTimer();
var timeInterval = setInterval(updateTimer, 1000);
}
</script>
<强> HTML:强>
<!DOCTYPE html>
<html>
<head>
<base target="_top">
<link href="https://ssl.gstatic.com/docs/script/css/add-ons1.css" rel="stylesheet">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js" type="text/javascript"></script>
</head>
<body>
<div id="mainForm">
<h1>Active Users</h1>
<div class="box">
Active Users Count:
<span id="activeUsersCount">0</span>
</div>
<div class="box">
Active Users:
<span id="activeUsers"></span>
</div>
<div class="box">
Polling in:
<span id="pollingIn"></span>
</div>
<div class="box">
You Are:
<span id="userID"></span>
</div>
</div>
<?!= HtmlService.createHtmlOutputFromFile('javascript').getContent(); ?>
<script>
var userID = <?= userID ?>;
</script>
</body>
</html>
<style>
.box {
display: block;
padding: 0.5em;
}
body {
padding: 1em;
}
</style>