• 关于

    timer定时器

    的搜索结果

回答

先创建定时器,拿到定时器句柄,再清楚该定时器单次定时// 创建定时器, 仅一秒后执行一次 var timer = setTimeout(function(){ console.log('something') }, 1000) // 清除定时器 clearTimeout(timer)循环定时// 创建定时器, 每秒执行一次 var timer = setInterval(function(){ console.log('something') }, 1000) // 清除定时器 clearInterval(timer)

albin.liao 2019-12-02 00:55:18 0 浏览量 回答数 0

问题

java Timer突然中止

长安归故里. 2020-01-07 13:37:19 0 浏览量 回答数 1

回答

Serverless 工作流本身没有提供定时触发工作流执行的功能,借助于函数计算 (FunctionCompute,简称 FC)的定时触器可以很方便的实现工作流定时调用。本文介绍如何使用 Serverless 工作流提供的定时触发工作流应用,来达到定时执行工作流的目的。 应用框架 定时触发工作流的执行流程如下: FC 定时触发器会定时执行 FC 函数。 FC 函数通过 Serverless 工作流 SDK 调用 StartExecution API 执行 Serverless 工作流。8b0732b23943d746 应用部署 创建定时触发工作流应用 在 Serverless 工作流应用中心 创建定时触发工作流应用。 81ade77a13121123 说明 应用名称:自定义的资源编排服务 ROS 资源栈名称,同一个账号下需保证唯一。 Cron 定时触发工作流的 Cron 表达式,参见 FC 定时触发器,默认为每分钟触发一次。 Input 触发执行工作流的输入,必须为 JSON 格式,默认为空。 部署成功后可看到应用创建的所有资源。de339104fa7aaff8其中包括: RAM 角色:fnf-timer-demo-serviceRole、fnf-timer-demo-flowRole。 FC 资源: 服务 fnf-timer-demo-service、函数 timer、函数 hello、定时触发器 trigger。 Serverless 工作流 资源:工作流 fnf-timer-demo-flow。 验证生效 前往 Serverless 工作流控制台可看到应用创建的工作流 fnf-timer-demo-flow 被定时触发 。17b3faa193bafe86示例工作流使用 任务步骤 调用 FC 函数 hello,定义如下。 version: v1 type: flow steps: - type: task name: hello resourceArn: 'acs:fc:::services/fnf-time-demo-service/functions/hello' 您可以修改该工作流的定义实现自身的业务逻辑。

1934890530796658 2020-03-27 10:52:42 0 浏览量 回答数 0

阿里云试用中心,为您提供0门槛上云实践机会!

0元试用32+款产品,最高免费12个月!拨打95187-1,咨询专业上云建议!

回答

Timer类不做为监听啊。它是个定时器Timer timer = new Timer();//使用timer对象的调度方法 (本示例为 方法延迟1秒执行并且之后每10秒执行1次)timer.schedule(new TimerTask() {@Override public void run() { //这里写要执行的方法 }},1000,1000*10);会定时调用要执行的代码块。如果想实现监听是要配合监听器使用的。Timer类本身只做任务功能。

蛮大人123 2019-12-02 02:23:11 0 浏览量 回答数 0

回答

通过定时器每秒调用播放器的getCurrentTime方法获取播放时间, 在暂停、出错和结束播放时清除定时器。 var timer = null; function getTime() { var currentTime = player.getCurrentTime(); //to do timer = setTimeout(getTime,1000); } //清除定时器 function clear() { if(timer) { clearTimeout(timer); timer = null; } } player.on('ended',function (e) { clear(); }); player.on('pause',function (e) { clear(); }); player.on('error',function (e) { clear(); });

保持可爱mmm 2020-03-30 14:28:51 0 浏览量 回答数 0

回答

结构 timer 就是 Golang 定时器的内部表示,每一个 timer 其实都存储在堆中,tb 就是用于存储当前定时器的桶,而 i 是当前定时器在堆中的索引,我们可以通过这两个变量找到当前定时器在堆中的位置: type timer struct { tb *timersBucket i int when int64 period int64 f func(interface{}, uintptr) arg interface{} seq uintptr } when 表示当前定时器(Timer)被唤醒的时间,而 period 表示两次被唤醒的间隔,每当定时器被唤醒时都会调用 f(args, now) 函数并传入 args 和当前时间作为参数。然而这里的 timer 作为一个私有结构体其实只是定时器的运行时表示,time 包对外暴露的定时器使用了如下所示的结构体: type Timer struct { C <-chan Time r runtimeTimer } Timer 定时器必须通过 NewTimer 或者 AfterFunc 函数进行创建,其中的 runtimeTimer 其实就是上面介绍的 timer 结构体,当定时器失效时,失效的时间就会被发送给当前定时器持有的 Channel C,订阅管道中消息的 Goroutine 就会收到当前定时器失效的时间。 在 time 包中,除了 timer 和 Timer 两个分别用于表示运行时定时器和对外暴露的 API 之外,timersBucket 这个用于存储定时器的结构体也非常重要,它会存储一个处理器上的全部定时器,不过如果当前机器的核数超过了 64 核,也就是机器上的处理器 P 的个数超过了 64 个,多个处理器上的定时器就可能存储在同一个桶中: type timersBucket struct { lock mutex gp *g created bool sleeping bool rescheduling bool sleepUntil int64 waitnote note t []*timer } 每一个 timersBucket 中的 t 就是用于存储定时器指针的切片,每一个运行的 Go 语言程序都会在内存中存储着 64 个桶,这些桶中都存储定时器的信息:  每一个桶持有的 timer 切片其实都是一个最小堆,这个最小堆会按照 timer 应该触发的时间对它们进行排序,最小堆最上面的定时器就是最近需要被唤醒的 timer,我们会在下面展开介绍定时器的创建和触发过程。 工作原理 既然我们已经介绍了定时器的数据结构,接下来我们就可以开始分析它的常见操作以及工作原理了,在这一节中我们将介绍定时器的创建、触发、time.Sleep 与定时器的关系以及计时器 Ticker 的实现原理。 创建 time 包对外提供了两种创建定时器的方法,第一种方法就是 NewTimer 接口,这个接口会创建一个用于通知触发时间的 Channel、调用 startTimer 方法并返回一个创建指向 Timer 结构体的指针: func NewTimer(d Duration) *Timer { c := make(chan Time, 1) t := &Timer{ C: c, r: runtimeTimer{ when: when(d), f: sendTime, arg: c, }, } startTimer(&t.r) return t } 另一个用于创建 Timer 的方法 AfterFunc 其实也提供了非常相似的结构,与 NewTimer 方法不同的是该方法没有创建一个用于通知触发时间的 Channel,它只会在定时器到期时调用传入的方法: func AfterFunc(d Duration, f func()) *Timer { t := &Timer{ r: runtimeTimer{ when: when(d), f: goFunc, arg: f, }, } startTimer(&t.r) return t } startTimer 基本上就是创建定时器的入口了,所有定时器的创建和重启基本上都需要调用该函数: func startTimer(t *timer) { addtimer(t) } func addtimer(t *timer) { tb := t.assignBucket() tb.addtimerLocked(t) } 它会调用 addTimer 函数,这个函数总共做了两件事情,首先通过 assignBucket 方法为当前定时器选择一个 timersBucket 桶,我们会根据当前 Goroutine 所在处理器 P 的 id 选择一个合适的桶,随后调用 addTimerLocked 方法将当前定时器加入桶中: func (tb *timersBucket) addtimerLocked(t *timer) bool { t.i = len(tb.t) tb.t = append(tb.t, t) if !siftupTimer(tb.t, t.i) { return false } if t.i == 0 { if tb.sleeping && tb.sleepUntil > t.when { tb.sleeping = false notewakeup(&tb.waitnote) } if tb.rescheduling { tb.rescheduling = false goready(tb.gp, 0) } if !tb.created { tb.created = true go timerproc(tb) } } return true } addtimerLocked 会先将最新加入的定时器加到队列的末尾,随后调用 siftupTimer 将当前定时器与四叉树(或者四叉堆)中的父节点进行比较,保证父节点的到期时间一定大于子节点:  这个四叉树只能保证父节点的到期时间大于子节点,这对于我们来说其实也足够了,因为我们只关心即将被触发的计数器,如果当前定时器是第一个被加入四叉树的定时器,我们还会通过 go timerproc(tb) 启动一个 Goroutine 用于处理当前树中的定时器,这也是处理定时器的核心方法。 触发 定时器的触发都是由 timerproc 中的一个双层 for 循环控制的,外层的 for 循环主要负责对当前 Goroutine 进行控制,它不仅会负责锁的获取和释放,还会在合适的时机触发当前 Goroutine 的休眠: func timerproc(tb *timersBucket) { tb.gp = getg() for { tb.sleeping = false now := nanotime() delta := int64(-1) // inner loop if delta < 0 { tb.rescheduling = true goparkunlock(&tb.lock, waitReasonTimerGoroutineIdle, traceEvGoBlock, 1) continue } tb.sleeping = true tb.sleepUntil = now + delta noteclear(&tb.waitnote) notetsleepg(&tb.waitnote, delta) } } 如果距离下一个定时器被唤醒的时间小于 0,当前的 timerproc 就会将 rescheduling 标记设置成 true 并立刻陷入休眠,这其实也意味着当前 timerproc 中不包含任何待处理的定时器,当我们再向该 timerBucket 加入定时器时就会重新唤醒 timerproc Goroutine。 在其他情况下,也就是下一次计数器的响应时间是 now + delta 时,timerproc 中的外层循环会通过 notesleepg 将当前 Goroutine 陷入休眠。 func notetsleepg(n *note, ns int64) bool { gp := getg() if gp == gp.m.g0 { throw("notetsleepg on g0") } semacreate(gp.m) entersyscallblock() ok := notetsleep_internal(n, ns, nil, 0) exitsyscall() return ok } 该函数会先获取当前的 Goroutine 并在当前的『CPU 上』创建一个信号量,随后在 entersyscallblock 和 exitsyscall 之间执行系统调用让当前的 Goroutine 陷入休眠并在 ns 纳秒后返回。 内部循环的主要作用就是触发已经到期的定时器,在这个内部循环中,我们会按照以下的流程对当前桶中的定时器进行处理: 如果桶中不包含任何定时器就会直接返回并陷入休眠等待定时器加入当前桶; 如果四叉树最上面的定时器还没有到期会通过 notetsleepg 方法陷入休眠等待最近定时器的到期; 如果四叉树最上面的定时器已经到期; 当定时器的 period > 0 就会设置下一次会触发定时器的时间并将当前定时器向下移动到对应的位置; 当定时器的 period <= 0 就会将当前定时器从四叉树中移除; 在每次循环的最后都会从定时器中取出定时器中的函数、参数和序列号并调用函数触发该计数器; ```js for { if len(tb.t) == 0 { delta = -1 break } t := tb.t[0] delta = t.when - now if delta > 0 { break } ok := true if t.period > 0 { t.when += t.period * (1 + -delta/t.period) if !siftdownTimer(tb.t, 0) { ok = false } } else { last := len(tb.t) - 1 if last > 0 { tb.t[0] = tb.t[last] tb.t[0].i = 0 } tb.t[last] = nil tb.t = tb.t[:last] if last > 0 { if !siftdownTimer(tb.t, 0) { ok = false } } t.i = -1 // mark as removed } f := t.f arg := t.arg seq := t.seq f(arg, seq) } 使用 NewTimer 创建的定时器,传入的函数时 sendTime,它会将当前时间发送到定时器持有的 Channel 中,而使用 AfterFunc 创建的定时器,在内层循环中调用的函数就会是调用方传入的函数了。 **休眠** 如果你使用过一段时间的 Go 语言,你一定在项目中使用过 time 包中的 Sleep 方法让当前的 Goroutine 陷入休眠以等待某些条件的完成或者触发一些定时任务,time.Sleep 就是通过如下所示的 timeSleep 方法完成的: ```js func timeSleep(ns int64) { if ns <= 0 { return } gp := getg() t := gp.timer if t == nil { t = new(timer) gp.timer = t } *t = timer{} t.when = nanotime() + ns t.f = goroutineReady t.arg = gp tb := t.assignBucket() lock(&tb.lock) if !tb.addtimerLocked(t) { unlock(&tb.lock) badTimer() } goparkunlock(&tb.lock, waitReasonSleep, traceEvGoSleep, 2) } timeSleep 会创建一个新的 timer 结构体,在初始化的过程中我们会传入当前 Goroutine 应该被唤醒的时间以及唤醒时需要调用的函数 goroutineReady,随后会调用 goparkunlock 将当前 Goroutine 陷入休眠状态,当定时器到期时也会调用 goroutineReady 方法唤醒当前的 Goroutine: func goroutineReady(arg interface{}, seq uintptr) { goready(arg.(*g), 0) } time.Sleep 方法其实只是创建了一个会在到期时唤醒当前 Goroutine 的定时器并通过 goparkunlock 将当前的协程陷入休眠状态等待定时器触发的唤醒。 Ticker 除了只用于一次的定时器(Timer)之外,Go 语言的 time 包中还提供了用于多次通知的 Ticker 计时器,计时器中包含了一个用于接受通知的 Channel 和一个定时器,这两个字段共同组成了用于连续多次触发事件的计时器: type Ticker struct { C <-chan Time // The channel on which the ticks are delivered. r runtimeTimer } 想要在 Go 语言中创建一个计时器只有两种方法,一种是使用 NewTicker 方法显示地创建Ticker 计时器指针,另一种可以直接通过 Tick 方法获取一个会定期发送消息的 Channel: func NewTicker(d Duration) *Ticker { if d <= 0 { panic(errors.New("non-positive interval for NewTicker")) } c := make(chan Time, 1) t := &Ticker{ C: c, r: runtimeTimer{ when: when(d), period: int64(d), f: sendTime, arg: c, }, } startTimer(&t.r) return t } func Tick(d Duration) <-chan Time { if d <= 0 { return nil } return NewTicker(d).C } Tick 其实也只是对 NewTicker 的简单封装,从实现上我们就能看出来它其实就是调用了 NewTicker 获取了计时器并返回了计时器中 Channel,两个创建计时器的方法的实现都并不复杂而且费容易理解,所以在这里也就不详细展开介绍了。 需要注意的是每一个 NewTicker 方法开启的计时器都需要在不需要使用时调用 Stop 进行关闭,如果不显示调用 Stop 方法,创建的计时器就没有办法被垃圾回收,而通过 Tick 创建的计时器由于只对外提供了 Channel,所以是一定没有办法关闭的,我们一定要谨慎使用这一接口创建计时器。 性能分析 定时器在内部使用四叉树的方式进行实现和存储,当我们在生产环境中使用定时器进行毫秒级别的计时时,在高并发的场景下会有比较明显的性能问题,我们可以通过实验测试一下定时器在高并发时的性能,假设我们有以下的代码: func runTimers(count int) { durationCh := make(chan time.Duration, count) wg := sync.WaitGroup{} wg.Add(count) for i := 0; i < count; i++ { go func() { startedAt := time.Now() time.AfterFunc(10*time.Millisecond, func() { defer wg.Done() durationCh <- time.Since(startedAt) }) }() } wg.Wait() close(durationCh) durations := []time.Duration{} totalDuration := 0 * time.Millisecond for duration := range durationCh { durations = append(durations, duration) totalDuration += duration } averageDuration := totalDuration / time.Duration(count) sort.Slice(durations, func(i, j int) bool { return durations[i] < durations[j] }) fmt.Printf("run %v timers with average=%v, pct50=%v, pct99=%v\n", count, averageDuration, durations[count/2], durations[int(float64(count)*0.99)]) } 完整的性能测试代码可以在 benchmark_timers.go 中找到,需要注意的是:由于机器和性能的不同,多次运行测试可能会有不一样的结果。 这段代码开了 N 个 Goroutine 并在每一个 Goroutine 中运行一个定时器,我们会在定时器到期时将开始计时到定时器到期所用的时间加入 Channel 并用于之后的统计,在函数的最后我们会计算出 N 个 Goroutine 中定时器到期时间的平均数、50 分位数和 99 分位数: $ go test ./... -v === RUN TestTimers run 1000 timers with average=10.367111ms, pct50=10.234219ms, pct99=10.913219ms run 2000 timers with average=10.431598ms, pct50=10.37367ms, pct99=11.025823ms run 5000 timers with average=11.873773ms, pct50=11.986249ms, pct99=12.673725ms run 10000 timers with average=11.954716ms, pct50=12.313613ms, pct99=13.507858ms run 20000 timers with average=11.456237ms, pct50=10.625529ms, pct99=25.246254ms run 50000 timers with average=21.223818ms, pct50=14.792982ms, pct99=34.250143ms run 100000 timers with average=36.010924ms, pct50=31.794761ms, pct99=128.089527ms run 500000 timers with average=176.676498ms, pct50=138.238588ms, pct99=676.967558ms --- PASS: TestTimers (1.21s) 我们将上述代码输出的结果绘制成如下图所示的折线图,其中横轴是并行定时器的个数,纵轴表示定时器从开始到触发时间的差值,三个不同的线分别表示时间的平均值、50 分位数和 99 分位数:  虽然测试的数据可能有一些误差,但是从图中我们也能得出一些跟定时器性能和现象有关的结论: 定时器触发的时间一定会晚于创建时传入的时间,假设定时器需要等待 10ms 触发,那它触发的时间一定是晚于 10ms 的; 当并发的定时器数量达到 5000 时,定时器的平均误差达到了 ~18%,99 分位数上的误差达到了 ~26%; 并发定时器的数量超过 5000 之后,定时器的误差就变得非常明显,不能有效、准确地完成计时任务; 这其实也是因为定时器从开始到触发的时间间隔非常短,当我们将计时的时间改到 100ms 时就会发现性能问题有比较明显的改善:  哪怕并行运行了 10w 个定时器,99 分位数的误差也只有 ~12%,我们其实能够发现 Go 语言标准库中的定时器在计时时间较短并且并发较高时有着非常明显的问题,所以在一些性能非常敏感的基础服务中使用定时器一定要非常注意 —— 它可能达不到我们预期的效果。 不过哪怕我们不主动使用定时器,而是使用 context.WithDeadline 这种方法,由于它底层也会使用定时器实现,所以仍然会受到影响。 总结 Go 语言的定时器在并发编程起到了非常重要的作用,它能够为我们提供比较准确的相对时间,基于它的功能,标准库中还提供了计时器、休眠等接口能够帮助我们在 Go 语言程序中更好地处理过期和超时等问题。 标准库中的定时器在大多数情况下是能够正常工作并且高效完成任务的,但是在遇到极端情况或者性能敏感场景时,它可能没有办法胜任,而在 10ms 的这个粒度下,作者在社区中也没有找到能够使用的定时器实现,一些使用时间轮算法的开源库也不能很好地完成这个任务。

有只黑白猫 2020-01-10 10:01:15 0 浏览量 回答数 0

回答

var timer = null; if (true) { // 开始定时器 timer = setTimeout(function() { // do what you want to do }, 0); } else { // 停止定时器 clearTimeout(timer); }

a123456678 2019-12-02 03:11:19 0 浏览量 回答数 0

问题

如何实现定时器控制自身的定时时间?

小旋风柴进 2019-12-01 19:37:45 835 浏览量 回答数 1

回答

你可以设置一个超时定时器在timeout设置的时间范围内如果发生触发了scroll事件,那么就将之前设置的定期器取消如果在指定的时间范围内没有滚动事件触发,那么执行removeClass的操作 var timer,timeout=1000; $(document).scroll(function(){ if(!timer){ $('body').addClass('pointer-none'); }else{ clearTimeout(timer); timer=null; } timer=setTimeout(function(){ $('body').removeClass('pointer-none'); next(); timer=null; }, timeout); });

杨冬芳 2019-12-02 02:36:46 0 浏览量 回答数 0

回答

相关知识点: // 思路是使用递归函数,不断地去执行 setTimeout 从而达到 setInterval 的效果 function mySetInterval(fn, timeout) { // 控制器,控制定时器是否继续执行 var timer = { flag: true }; // 设置递归函数,模拟定时器执行。 function interval() { if (timer.flag) { fn(); setTimeout(interval, timeout); } } // 启动定时器 setTimeout(interval, timeout); // 返回控制器 return timer; } 回答: setInterval 的作用是每隔一段指定时间执行一个函数,但是这个执行不是真的到了时间立即执行,它真正的作用是每隔一段时间将事件加入事件队列中去,只有当当前的执行栈为空的时候,才能去从事件队列中取出事件执行。所以可能会出现这样的情况,就是当前执行栈执行的时间很长,导致事件队列里边积累多个定时器加入的事件,当执行栈结束的时候,这些事件会依次执行,因此就不能到间隔一段时间执行的效果。 针对 setInterval 的这个缺点,我们可以使用 setTimeout 递归调用来模拟 setInterval,这样我们就确保了只有

剑曼红尘 2020-04-07 20:49:42 0 浏览量 回答数 0

回答

jmeter中使用集合点的方法:Synchronizing Timer 将测试元件Synchronizing Timer添加到请求之前或某个Sampler的子节点,右键菜单依次选择“添加–>定时器/Timer–>Synchronizing Timer“ 参考下面的博文 http://my.oschina.net/u/2318764/blog/378762

爱吃鱼的程序员 2020-06-03 20:43:14 0 浏览量 回答数 0

回答

tick一般是作为任务延迟调度的内部机制,其接口主要是系统内部使用。对于使用os的应用软件,也需要定时触发相关功能的接口,包括单次定时器和周期定时器。 从用户层面来讲,不关注底层cpu的定时机制以及tick的调度,用户希望的定时器接口是,可以创建和使能一个软件接口定时器,时间到了之后,用户的钩子函数能被执行。而对于操作系统的定时器本身来讲,其也需要屏蔽底层定时模块的差异。因此,在软件层次上,对于定时器硬件相关的操作由tick模块完成,定时器(timer)模块基于tick作为最基本的时间调度单元,即最小时间周期,来推动自己时间轴的运行。

剑曼红尘 2020-03-26 21:33:47 0 浏览量 回答数 0

回答

//鼠标悬浮停止定时器 stage.hover(function() { clearInterval(timer); }, function() { setInterval(autoPlay,1000); //这里你的第二次hover事件就找不到上次的timer了, 因此你这里要定义一个timer = setInterval();

小旋风柴进 2019-12-02 02:28:17 0 浏览量 回答数 0

回答

可以在beforeDestroy里写清除函数 const timer = setInterval(() =>{ // 某些定时器操作 }, 500); // 通过$once来监听定时器,在beforeDestroy钩子可以被清除。 this.$once('hook:beforeDestroy', () => { clearInterval(timer); }) 问题来源于GitHub,查看更多答案,请查看https://github.com/haizlin/fe-interview/issues/446

游客7iokfgo4yexey 2020-05-23 12:53:55 0 浏览量 回答数 0

回答

spring定时器TimerTask用法:在tomcat服务启动,spring定时器容器加载时会执行定时器里的任务,可设置时间间隔和延迟执行时间,具体做法如下: 定时器Java代码: package com.coalmine.desktop; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Date; import java.util.TimerTask; public class Task extends TimerTask { @Override //定时器入口,run()里面是你的任务作业 public void run() { SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); Date date = new Date(); System.out.println(sdf.format(date) + " 执行TimerTask定时器==============="); } } applicationContext.xml配置如下: <!-- spring定时任务配置 --> <bean id="deskTask" class="com.coalmine.desktop.Task"></bean> <bean id="scheduledTask" class="org.springframework.scheduling.timer.ScheduledTimerTask"> <property name="timerTask"> <ref bean="deskTask" /> </property> <!--任务执行周期 5s (此处单位是毫秒)--> <property name="period"> <value>5000</value> </property> <!--延时10s 执行任务 --> <property name="delay"> <value>10000</value> </property> </bean> <!--启动定时器 --> <bean id="timerBean" class="org.springframework.scheduling.timer.TimerFactoryBean"> <property name="scheduledTimerTasks"> <list> <ref bean="scheduledTask" /> </list> </property> </bean> OK,就这么简单,当启动服务后加载完定时器,延迟10秒后,每隔5秒执行一次run()

小旋风柴进 2019-12-02 01:57:10 0 浏览量 回答数 0

回答

请搜索一下setInterval方法,setInterval会创建一个异步线程,返回是这个线程的ID。 多次点击,会创建多个线程。timer被赋值到最后一个线程的ID,停止了的也是最后一个线程。还有其他异步线程在跑着,没有停止。 可以在handleTimer函数中打印一下timer就明白了。 解决办法:1- 倒数期间,对元素解绑事件。2- 单一设计模式,判断timer是否被赋值。 方法2: var curTime = 0, timer = null, btn = $('#button'); btn.on('click',function(){ if(timer === null){ curTime = 3; timer = setInterval(handleTimer, 1000); } }); function handleTimer(){ console.log(timer); if(curTime === 0){ clearInterval(timer); timer = null; btn.text('重新发送验证码'); }else{ btn.text(curTime + '秒后可重新发送'); curTime --; } } 看了一下其他答案,均在click中clearInterval清除计时器,这样的确可以修复问题,但是同时存在另外问题:1- 多次按下btn,多次清除定时器,性能问题。2- 正在倒计时的时候应该禁用掉功能函数,不应再触发重新倒计时。 // var timer = null; $("#sendsms").on("click",function(){ var phone=$("#form_phone").val(); if(phone!="" && timer == null){ curTime=countTime; $("#sendsms").attr("disabled","true"); $("#sendsms").text(curTime+"秒后可重新发送"); timer=setInterval(handleTimer, 1000); } }); function handleTimer(){ if(curTime==0){ clearInterval(timer); timer=null; $("#sendsms").removeAttr("disabled"); $("#sendsms").text("重新发送验证码"); } else{ curTime--; $("#sendsms").text(curTime+"秒后可重新发送"); } }

杨冬芳 2019-12-02 02:33:43 0 浏览量 回答数 0

问题

java如何在在timer里传递全局变量?

蛮大人123 2019-12-01 20:15:48 1262 浏览量 回答数 2

回答

// 函数防抖: 在事件被触发 n 秒后再执行回调,如果在这 n 秒内事件又被触发,则重新计时。 // 函数节流: 规定一个单位时间,在这个单位时间内,只能有一次触发事件的回调函数执行,如果在同一个单位时间内某事件被触发多次,只有一次能生效。 // 函数防抖的实现 function debounce(fn, wait) { var timer = null; return function() { var context = this, args = arguments; // 如果此时存在定时器的话,则取消之前的定时器重新记时 if (timer) { clearTimeout(timer); timer = null; } // 设置定时器,使事件间隔指定事件后执行 timer = setTimeout(() => { fn.apply(context, args); }, wait); }; } // 函数节流的实现; function throttle(fn, delay) { var preTime = Date.now(); return function() { var context = this, args = arguments, nowTime = Date.now(); // 如果两次时间间隔超过了指定时间,则执行函数。 if (nowTime - preTime >= delay) { preTime = Date.now(); return fn.apply(context, args); } }; } 回答: 函数防抖是指在事件被触发 n 秒后再执行回调,如果在这 n 秒内事件又被触发,则重新计时。这可以使用在一些点击请求的事件上,避免因为用户的多次点击向后端发送多次请求。 函数节流是指规定一个单位时间,在这个单位时间内,只能有一次触发事件的回调函数执行,如果在同一个单位时间

剑曼红尘 2020-04-05 21:35:49 0 浏览量 回答数 0

回答

clear掉定时器就行了,然后$(".dis").hide(); $(function(){ var _time = 3000; var timer3 = null; $('.show').click(function(){ timer3 = setTimeout(function(){ $(".dis").hide(); },_time); }) window.scroll(function(){ clearTimeout(timer3); $(".dis").hide(); })

小旋风柴进 2019-12-02 02:28:00 0 浏览量 回答数 0

问题

Javascript怎么实现滑动效果的方法?

杨冬芳 2019-12-01 20:06:54 906 浏览量 回答数 1

回答

timer定时器

黄二刀 2020-05-11 16:39:13 0 浏览量 回答数 0

回答

qaurtz 这个功能还是比较的强大的,自带的例子有基于数据库的定时器。嫌麻烦可以直接使用 Java 的 timer和TimerTask 。 最简单的就是使用Linux 的Cron 把你要执行的代码打包为jar 然后定时执行就可以了。 你说用数据库。 这个定时查询就行了来个最简单的//记得抛在线程里面就可以了 while(true){ // query Thread.sleep(1000); }

a123456678 2019-12-02 02:12:50 0 浏览量 回答数 0

回答

在线程中使用 System.Windows.Forms.Timer 是不能触发 Tick 事件的,为什么?如何在线程中使用定时器呢?就看本文介绍。 一. System.Windows.Forms.Timer System.Windows.Forms.Timer 要求要有UI 消息泵, 所以通常只在主线程上使用. System.Windows.Forms.Timer 用于以用户定义的事件间隔触发事件。 Windows 计时器是为单线程环境设计的,其中,UI 线程用于执行处理。 它要求用户代码有一个可用的 UI 消息泵,而且总是在同一个线程中操作,或者将调用封送到另一个线程. 且看MSDN的用法解释: 实现在用户定义的时间间隔引发事件的计时器。此计时器最宜用于 Windows 窗体应用程序中,并且必须在窗口中使用。 二. System.Timers.Timer System.Timers.Timer 组件是基于服务器的计时器,它使您能够指定在应用程序中引发 Elapsed 事件的周期性间隔。 然后可以操控此事件以提供定期处理。例如,假设您有一台关键性服务器,必须每周 7 天、每天 24 小时都保持运行。 可以创建一个使用 Timer 的服务,以定期检查服务器并确保系统开启并在运行。如果系统不响应,则该服务可以尝试重新启动服务器或通知管理员。 基于服务器的 Timer 是为在多线程环境中用于辅助线程而设计的。 服务器计时器可以在线程间移动来处理引发的 Elapsed 事件,这样就可以比 Windows 计时器更精确地按时引发事件。 有关基于服务器的计时器的更多信息,请参见“基于服务器的计时器介绍”。 在 Visual Studio 和 .NET Framework 中有三种计时器控件:基于服务器的计时器(可以在“工具箱”的“组件”选项卡上看到)、基于 Windows 的标准计时器(可以在“工具箱”的“Windows 窗体”选项卡上看到)和线程计时器(只能以编程方式使用)。 基于 Windows 的计时器从 Visual Basic 1.0 版起就存在于该产品中,并且基本上未做改动。该计时器针对在 Windows 窗体应用程序中使用而进行了优化。 基于服务器的计时器是传统的计时器为了在服务器环境上运行而优化后的更新版本。 线程计时器是一种简单的、轻量级计时器,它使用回调方法而不是使用事件,并由线程池线程提供支持。 在 Win32 体系结构中有两种类型的线程:UI 线程和辅助线程。UI 线程绝大多数时间处于空闲状态,等待消息循环中的消息到来。 一旦接收到消息,它们就进行处理并等待下一个消息到来。另外,辅助线程用来执行后台处理而且不使用消息循环。 Windows 计时器和基于服务器的计时器在运行时都使用 Interval 属性。线程计时器的时间间隔在 Timer 构造函数中设置。 计时器的设计目的各不相同,它们的线程处理明确地指出了这一点: 1.Windows 计时器是为单线程环境设计的,其中,UI 线程用于执行处理。Windows 计时器的精度限定为 55 毫秒。 这些传统计时器要求用户代码有一个可用的 UI 消息泵,而且总是在同一个线程中操作,或者将调用封送到另一个线程。对于 COM 组件来说,这样会降低性能。 2.基于服务器的计时器是为在多线程环境下与辅助线程一起使用而设计的。由于它们使用不同的体系结构,因此基于服务器的计时器可能比 Windows 计时器精确得多。 服务器计时器可以在线程之间移动来处理引发的事件。 3.对消息不在线程上发送的方案中,线程计时器是非常有用的。例如,基于 Windows 的计时器依赖于操作系统计时器的支持,如果不在线程上发送消息,与计时器相关的事件将不会发生。 在这种情况下,线程计时器就非常有用。 “答案来源于网络,供您参考” 希望以上信息可以帮到您!

牧明 2019-12-02 02:17:14 0 浏览量 回答数 0

问题

定时器关闭失败,点击取消后定时器的时间越来越短,下面是代码

小旋风柴进 2019-12-01 20:22:31 1265 浏览量 回答数 0

回答

直接用java 的Timer 和TimerTask放在servlet的init() 方法里 启动就加载 定时器。比spring 好多了。

a123456678 2019-12-02 02:10:28 0 浏览量 回答数 0

问题

用定时器做一个发送验证码的倒计时遇到的问题?

杨冬芳 2019-12-01 19:42:10 1007 浏览量 回答数 1

回答

while(true){ 轮训代码,写在这里就可以了,如果需要你可以在加入判断逻辑,也可以使用timer定时器实现。}

徐雷frank 2019-12-02 01:04:03 0 浏览量 回答数 0

回答

你猜############f12######被动式刷新,或者定时器。我猜的。###### 前端定时刷新,以下链接就是的。20s请求一次。 http://www.oschina.net/widgets/check-top-log?last=4734480   ######timer(check_new_log,20000);

爱吃鱼的程序员 2020-05-30 21:41:21 0 浏览量 回答数 0

回答

你可以使用 NSTimer 来实现定时轮询的方案 示例代码 NSTimer *timer = [NSTimer timerWithTimeInterval:3 target:self selector:@selector(timerEvent) userInfo:nil repeats:YES]; - 3 表示的就是时间间隔,设置成你需要的时间 - timerEvent 方法就是每次定时器触发时调用的方法,在这个里面写你需要的轮询调用,一般就是请求对应的服务获取结果 - repeats 设置成 YES 就是表示一直循环触发下去,所以记得在适当的时候把它关掉 (切记!!)

sherlockyao 2019-12-02 00:56:22 0 浏览量 回答数 0

问题

写在flink process里的onTimer,是不是每有一个数据被处理就会注册一 #Flink

黄一刀 2020-05-14 15:46:39 2 浏览量 回答数 1
阿里云大学 云服务器ECS com域名 网站域名whois查询 开发者平台 小程序定制 小程序开发 国内短信套餐包 开发者技术与产品 云数据库 图像识别 开发者问答 阿里云建站 阿里云备案 云市场 万网 阿里云帮助文档 免费套餐 开发者工具 企业信息查询 小程序开发制作 视频内容分析 企业网站制作 视频集锦 代理记账服务 2020阿里巴巴研发效能峰会 企业建站模板 云效成长地图 高端建站