- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
目前,我正在使用Grails创建一个基于Web的数据加载应用程序,简而言之,它会使用任意行的excel表格并将其运行在后端系统中,以为测试人员准备数据。
一切工作正常,但我需要做的最后一件事是通知用户(特别是在大型数据文件上)已处理了多少行数据的方法。如果行数超过200,即使该应用仍然运行缓慢,该应用也会显示超时。这是一个问题,因为用户很可能会重新加载文件并弄乱处理……重复的测试数据行将导致一系列下游问题。
我正在玩代码here。
<g:actionSubmit action="${appContext}/FileUploader.processFile" value="Upload File" onclick="download()"></g:actionSubmit>
<script type="text/javascript">
dojo.require("dijit.ProgressBar");
dojo.require("dojo.parser");
var i = 0;
function download() {
jsProgress.update({
maximum: 10,
progress: ++i
});
if (i < 10) {
setTimeout(download, 100 + Math.floor(Math.random() * 100));
}
}
</script>
def updateStatus = {
render uploaderService.rowsLoaded / uploaderService.listToSend.size()
}
progress
代码。)
最佳答案
首先,您可能要启动后台作业中的进程并将处理消息返回给用户
这是一个如何使用jprogress和executer插件执行此操作的示例。不幸的是,这使用了轮询解决方案。我还没有弄清楚如何使用JMS触发更新。
域
package jprogressdemo
class Event {
String name
Integer duration = 100
String status = "New"
Integer percentComplete = 0
static mapping = {
cache false
}
static constraints = {
name(size:1..45, unique:true )
duration()
status(size:1..5)
percentComplete()
}
}
package jprogressdemo
class EventController {
//static allowedMethods = [save: "POST", update: "POST", delete: "POST"]
def progressService
def jmsService
static exposes = ['jms']
static destination = "queue.notification"
def executeAction = {
println "executeAction"
def theEvent = Event.get(params.id)
def duration = theEvent?.duration ?: 10
def name = theEvent?.name.trim() ?: "none"
def startAt = theEvent?.percentComplete ?: 0
toEvent(name,duration,startAt,true)
render "the progress is done"
}
/*
* Start the backgorund task then
* while %complete < 100, query db and update progressbar.
*/
//the progress bar id needs to the same value that's passed into .setProgressBarValue
def backgroundAction = {
println "backgroundAction"
println "isDisabled():${jmsService.isDisabled()}"
def theEvent = Event.get(params.id)
def duration = theEvent?.duration ?: 10
def name = theEvent?.name ?: "none"
def barName = "${name}b"
def percentComplete = theEvent?.percentComplete ?: 0
def lastPct = -1
runAsync {
toEvent(name,duration,percentComplete,false)
}
if (percentComplete > 100) {progressService.setProgressBarValue(barName, 100)}
//can't be factored out because it's this function that
// gets called from the client ????
while(percentComplete <= 100) {
println "percentComplete:${percentComplete}"
if (percentComplete != lastPct ) {
progressService.setProgressBarValue(barName, percentComplete)
lastPct = percentComplete
}
def newEvent = Event.get(params.id)
newEvent.refresh()
percentComplete = theEvent.percentComplete
}
render "the progress is done"
}
//the progress bar id needs to the same value that's passed into .setProgressBarValue
def backgroundProgress = {
def theEvent = Event.get(params.id)
def duration = theEvent?.duration ?: 10
def name = theEvent?.name ?: "none"
def barName = "${name}p"
def percentComplete = theEvent?.percentComplete ?: 0
def lastPct = -1
if (percentComplete > 100) {progressService.setProgressBarValue(barName, 100)}
while(percentComplete <= 100) {
println "percentComplete:${percentComplete}"
if (percentComplete != lastPct ) {
progressService.setProgressBarValue(barName, percentComplete)
lastPct = percentComplete
}
def newEvent = Event.get(params.id)
newEvent.refresh()
percentComplete = theEvent.percentComplete
}
}
/*
% complete needs to get to 101 to avoid infinit loop in polling logic
And you can't go from 0-99 because the progress bar doesn't register a 0
*/
def toEvent(name,duration,startAt,updateBar) {
println "duration:${duration}"
println "name:${name}"
println "startat:${startAt}"
for (int i = startAt; i < 102; i++) {
println "i:${i}"
def theEvent = Event.findByName(name)
theEvent.percentComplete = i
theEvent.save(flush:true)
println "theEvent.percentComplete:${theEvent.percentComplete}"
if(updateBar){
progressService.setProgressBarValue(name, i)
} else {
sendJMSMessage("queue.notification", "${i}")
}
//let's waste some time
for (int a = 0; a < duration; a++) {
for (int b = 0; b < 1000; b++) {
}
}
}
}
def index = {
redirect(action: "list", params: params)
}
def list = {
params.max = Math.min(params.max ? params.int('max') : 10, 100)
[eventInstanceList: Event.list(params), eventInstanceTotal: Event.count()]
}
def create = {
def eventInstance = new Event()
eventInstance.properties = params
return [eventInstance: eventInstance]
}
def save = {
def eventInstance = new Event(params)
if (eventInstance.save(flush: true)) {
flash.message = "${message(code: 'default.created.message', args: [message(code: 'event.label', default: 'Event'), eventInstance.id])}"
redirect(action: "show", id: eventInstance.id)
}
else {
render(view: "create", model: [eventInstance: eventInstance])
}
}
def show = {
def eventInstance = Event.get(params.id)
if (!eventInstance) {
flash.message = "${message(code: 'default.not.found.message', args: [message(code: 'event.label', default: 'Event'), params.id])}"
redirect(action: "list")
}
else {
[eventInstance: eventInstance]
}
}
def edit = {
def eventInstance = Event.get(params.id)
if (!eventInstance) {
flash.message = "${message(code: 'default.not.found.message', args: [message(code: 'event.label', default: 'Event'), params.id])}"
redirect(action: "list")
}
else {
return [eventInstance: eventInstance]
}
}
def update = {
def eventInstance = Event.get(params.id)
if (eventInstance) {
if (params.version) {
def version = params.version.toLong()
if (eventInstance.version > version) {
eventInstance.errors.rejectValue("version", "default.optimistic.locking.failure", [message(code: 'event.label', default: 'Event')] as Object[], "Another user has updated this Event while you were editing")
render(view: "edit", model: [eventInstance: eventInstance])
return
}
}
eventInstance.properties = params
if (!eventInstance.hasErrors() && eventInstance.save(flush: true)) {
flash.message = "${message(code: 'default.updated.message', args: [message(code: 'event.label', default: 'Event'), eventInstance.id])}"
redirect(action: "show", id: eventInstance.id)
}
else {
render(view: "edit", model: [eventInstance: eventInstance])
}
}
else {
flash.message = "${message(code: 'default.not.found.message', args: [message(code: 'event.label', default: 'Event'), params.id])}"
redirect(action: "list")
}
}
def delete = {
def eventInstance = Event.get(params.id)
if (eventInstance) {
try {
eventInstance.delete(flush: true)
flash.message = "${message(code: 'default.deleted.message', args: [message(code: 'event.label', default: 'Event'), params.id])}"
redirect(action: "list")
}
catch (org.springframework.dao.DataIntegrityViolationException e) {
flash.message = "${message(code: 'default.not.deleted.message', args: [message(code: 'event.label', default: 'Event'), params.id])}"
redirect(action: "show", id: params.id)
}
}
else {
flash.message = "${message(code: 'default.not.found.message', args: [message(code: 'event.label', default: 'Event'), params.id])}"
redirect(action: "list")
}
}
}
<%@ page import="jprogressdemo.Event" %>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<meta name="layout" content="main" />
<g:javascript library="jquery" plugin="jquery"/>
<jqui:resources/>
<g:set var="entityName" value="${message(code: 'event.label', default: 'Event')}" />
<title><g:message code="default.show.label" args="[entityName]" /></title>
</head>
<body>
<div class="nav">
<span class="menuButton"><a class="home" href="${createLink(uri: '/')}"><g:message code="default.home.label"/></a></span>
<span class="menuButton"><g:link class="list" action="list"><g:message code="default.list.label" args="[entityName]" /></g:link></span>
<span class="menuButton"><g:link class="create" action="create"><g:message code="default.new.label" args="[entityName]" /></g:link></span>
</div>
<div class="body">
<h1><g:message code="default.show.label" args="[entityName]" /></h1>
<g:if test="${flash.message}">
<div class="message">${flash.message}</div>
</g:if>
<div class="dialog">
<table>
<tbody>
<tr class="prop">
<td valign="top" class="name"><g:message code="event.id.label" default="Id" /></td>
<td valign="top" class="value">${fieldValue(bean: eventInstance, field: "id")}</td>
</tr>
<tr class="prop">
<td valign="top" class="name"><g:message code="event.name.label" default="Name" /></td>
<td valign="top" class="value">${fieldValue(bean: eventInstance, field: "name")}</td>
</tr>
<tr class="prop">
<td valign="top" class="name"><g:message code="event.duration.label" default="Duration" /></td>
<td valign="top" class="value">${fieldValue(bean: eventInstance, field: "duration")}</td>
</tr>
<tr class="prop">
<td valign="top" class="name"><g:message code="event.status.label" default="Status" /></td>
<td valign="top" class="value">${fieldValue(bean: eventInstance, field: "status")}</td>
</tr>
<tr class="prop">
<td valign="top" class="name"><g:message code="event.percentComplete.label" default="Percent Complete" /></td>
<td valign="top" class="value">${fieldValue(bean: eventInstance, field: "percentComplete")}</td>
</tr>
</tbody>
</table>
</div>
<div class="buttons">
<g:form>
<g:hiddenField name="id" value="${eventInstance?.id}" />
<span class="button"><g:actionSubmit class="edit" action="edit" value="${message(code: 'default.button.edit.label', default: 'Edit')}" /></span>
<span class="button"><g:actionSubmit class="delete" action="delete" value="${message(code: 'default.button.delete.label', default: 'Delete')}" onclick="return confirm('${message(code: 'default.button.delete.confirm.message', default: 'Are you sure?')}');" /></span>
</g:form>
</div>
<p>
<HR WIDTH="75%" COLOR="#FF0000" SIZE="4"/>
<g:form>
<g:hiddenField name="id" value="${eventInstance?.id}"/>
<g:submitToRemote action="executeAction" name="startButton" value="start...."/>
<g:submitToRemote action="backgroundAction" name="backgroundButton" value="background...."/>
<g:submitToRemote action="backgroundProgress" name="progressButton" value="progress...."/>
</g:form>
<g:jprogress progressId="${eventInstance?.name}" trigger="startButton"/>
<g:jprogress progressId="${eventInstance?.name}b" trigger="backgroundButton"/>
<g:jprogress progressId="${eventInstance?.name}p" trigger="progressButton"/>
</div>
</body>
</html>
关于ajax - Grails/Dojo进度栏从 Controller /服务获取进度,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7612820/
我需要您在以下方面提供帮助。近一个月来,我一直在阅读有关任务和异步的内容。 我想尝试在一个简单的 wep api 项目中实现我新获得的知识。我有以下方法,并且它们都按预期工作: public Htt
我的可执行 jar 中有一个模板文件 (.xls)。不需要在运行时我需要为这个文件创建 100 多个副本(稍后将唯一地附加)。用于获取 jar 文件中的资源 (template.xls)。我正在使用
我在查看网站的模型代码时对原型(prototype)有疑问。我知道这对 Javascript 中的继承很有用。 在这个例子中... define([], function () { "use
影响我性能的前三项操作是: 获取滚动条 获取偏移高度 Ext.getStyle 为了解释我的应用程序中发生了什么:我有一个网格,其中有一列在每个单元格中呈现网格。当我几乎对网格的内容做任何事情时,它运
我正在使用以下函数来获取 URL 参数。 function gup(name, url) { name = name.replace(/[\[]/, '\\\[').replace(/[\]]/,
我最近一直在使用 sysctl 来做很多事情,现在我使用 HW_MACHINE_ARCH 变量。我正在使用以下代码。请注意,当我尝试获取其他变量 HW_MACHINE 时,此代码可以完美运行。我还认为
关闭。这个问题不符合Stack Overflow guidelines .它目前不接受答案。 关闭 9 年前。 要求提供代码的问题必须表现出对所解决问题的最低限度的理解。包括尝试过的解决方案、为什么
由于使用 main-bower-files 作为使用 Gulp 的编译任务的一部分,我无法使用 node_modules 中的 webpack 来require 模块code> dir 因为我会弄乱当
关闭。这个问题需要更多focused .它目前不接受答案。 想改进这个问题吗? 更新问题,使其只关注一个问题 editing this post . 关闭 5 年前。 Improve this qu
我使用 Gridlayout 在一行中放置 4 个元素。首先,我有一个 JPanel,一切正常。对于行数变大并且我必须能够向下滚动的情况,我对其进行了一些更改。现在我的 JPanel 上添加了一个 J
由于以下原因,我想将 VolumeId 的值保存在变量中: #!/usr/bin/env python import boto3 import json import argparse import
我正在将 MSAL 版本 1.x 更新为 MSAL-browser 的 Angular 。所以我正在尝试从版本 1.x 迁移到 2.X.I 能够成功替换代码并且工作正常。但是我遇到了 acquireT
我知道有很多关于此的问题,例如 Getting daily averages with pandas和 How get monthly mean in pandas using groupby但我遇到
This is the query string that I am receiving in URL. Output url: /demo/analysis/test?startDate=Sat+
我正在尝试使用 javascript 中的以下代码访问 Geoserver 层 var gkvrtWmsSource =new ol.source.ImageWMS({ u
API 需要一个包含授权代码的 header 。这就是我到目前为止所拥有的: var fullUrl = 'https://api.ecobee.com/1/thermostat?json=\{"s
如何获取文件中的最后一个字符,如果是某个字符,则删除它而不将整个文件加载到内存中? 这就是我目前所拥有的。 using (var fileStream = new FileStream("file.t
我是这个社区的新手,想出了我的第一个问题。 我正在使用 JSP,我成功地创建了 JSP-Sites,它正在使用jsp:setParameter 和 jsp:getParameter 具有单个字符串。
在回答 StoreStore reordering happens when compiling C++ for x86 @Peter Cordes 写过 For Acquire/Release se
我有一个函数,我们将其命名为 X1,它返回变量 Y。该函数在操作 .on("focusout", X1) 中使用。如何获取变量Y?执行.on后X1的结果? 最佳答案 您可以更改 Y 的范围以使其位于函
我是一名优秀的程序员,十分优秀!