问题描述
我对编程有点陌生,但是最近我尝试做我的第一个小项目叫计时器计数,这只是一个简单的本地网站,当我决定在白天开始编程时,我会打开它,并且计数时间。我创建了具有2个不同功能(启动,停止)的2个按钮,但是我遇到的问题是我不知道如何实现停止功能。这个想法是计时器应该在单击按钮后停止,而当我单击开始按钮时,它应该从节省的时间开始。 这是HTML / CSS代码:
<div class="timer-display-id">
<h1>Timer </h1>
<p id="timer">00:00:00 </p>
<button id="start-timer" onclick="start()">Start </button>
<button id="stop-timer" onclick="stop()">Stop </button>
</div>
<script src="timer.js"></script>
这是JS代码:
function stop() {
// not exactly sure if this function should be here,anyway no idea what to add to get this to work
clearInterval(interval);
start.disabled = false;
}
function convertSec(cnt) {
let sec = cnt % 60;
let min = Math.floor(cnt / 60);
if (sec < 10) {
if (min < 10) {return "0" + min + ":0" + sec;}
else {return min + ":0" + sec;}
}
else if ((min < 10) && (sec >= 10)) {return "0" + min + ":" + sec;}
else {return min + ":" + sec;}
}
function start() {
let ret = document.getElementById("timer");
let counter = 0;
let start = document.querySelector("#start-timer");
let stop = document.querySelector("#stop-timer");
start.disabled = true;
let interval = setInterval(function() {
ret.innerHTML = convertSec(counter++); // timer start counting here...
},1000);
}
我知道这可能非常混乱,缺乏逻辑,但是我现在最好能做到。如果您想提供有关代码组织的一些技巧,我将不胜感激。
解决方法
在拥有defmodule MyApp.Plug.PublicIp do
@moduledoc "Get public IP address of request from x-forwarded-for header"
@behaviour Plug
@app :my_app
def init(opts),do: opts
def call(%{assigns: %{ip: _}} = conn,_opts),do: conn
def call(conn,_opts) do
process(conn,Plug.Conn.get_req_header(conn,"x-forwarded-for"))
end
def process(conn,[]) do
Plug.Conn.assign(conn,:ip,to_string(:inet.ntoa(get_peer_ip(conn))))
end
def process(conn,vals) do
if Application.get_env(@app,:trust_x_forwarded_for,false) do ip_address = get_ip_address(conn,vals) # Rewrite standard remote_ip field with value from header
# See https://hexdocs.pm/plug/Plug.Conn.html
conn = %{conn | remote_ip: ip_address}
Plug.Conn.assign(conn,to_string(:inet.ntoa(ip_address)))
else
Plug.Conn.assign(conn,to_string(:inet.ntoa(get_peer_ip(conn))))
end
end
defp get_ip_address(conn,vals)
defp get_ip_address(conn,[]),do: get_peer_ip(conn)
defp get_ip_address(conn,[val | _]) do
# Split into multiple values
comps = val
|> String.split(~r{\s*,\s*},trim: true)
|> Enum.filter(&(&1 != "unknown")) # Get rid of "unknown" values
|> Enum.map(&(hd(String.split(&1,":")))) # Split IP from port,if any
|> Enum.filter(&(&1 != "")) # Filter out blanks
|> Enum.map(&(parse_address(&1))) # Parse address into :inet.ip_address tuple
|> Enum.filter(&(is_public_ip(&1))) # Elminate internal IP addreses,e.g. 192.168.1.1
case comps do
[] -> get_peer_ip(conn)
[comp | _] -> comp
end
end
@spec get_peer_ip(Plug.Conn.t) :: :inet.ip_address
defp get_peer_ip(conn) do
{ip,_port} = conn.peer
ip
end
@spec parse_address(String.t) :: :inet.ip_address
defp parse_address(ip) do
case :inet.parse_ipv4strict_address(to_charlist(ip)) do
{:ok,ip_address} -> ip_address
{:error,:einval} -> :einval
end
end
# Whether the input is a valid,public IP address
# http://en.wikipedia.org/wiki/Private_network
@spec is_public_ip(:inet.ip_address | atom) :: boolean
defp is_public_ip(ip_address) do
case ip_address do
{10,_,_} -> false
{192,168,_} -> false
{172,second,_} when second >= 16 and second <= 31 -> false
{127,_} -> false
{_,_} -> true
:einval -> false
end
end
end
函数的同时,两个函数都可以访问interval
,只需将其移到setInterval
函数之外即可:
start
const ret = document.getElementById("timer");
const startBtn = document.querySelector("#start-timer");
let counter = 0;
let interval;
function stop() {
clearInterval(interval);
startBtn.disabled = false;
}
function convertSec(cnt) {
let sec = cnt % 60;
let min = Math.floor(cnt / 60);
if (sec < 10) {
if (min < 10) {
return "0" + min + ":0" + sec;
} else {
return min + ":0" + sec;
}
} else if ((min < 10) && (sec >= 10)) {
return "0" + min + ":" + sec;
} else {
return min + ":" + sec;
}
}
function start() {
startBtn.disabled = true;
interval = setInterval(function() {
ret.innerHTML = convertSec(counter++); // timer start counting here...
},1000);
}
,
如果您希望在点击“停止”后保存计数并从同一点重新开始,则需要在count
函数外部的某个位置定义start()
变量,这样它可以告诉您重新开始计数的次数。目前,count
是start()
函数的本地函数,它将每次将其重置为零。
通过使用1秒间隔计时器更新计数,您的计数器会将每个时间段舍入为整秒。这样做会稍微复杂一些,但是如果您希望能够将多个计数中的部分秒数相加,使用类似Date.getTime()的方法来记录按下开始按钮的时间会更准确,然后检查stop()
触发时所经过的时间,并将其添加到您的计数中。但是,您可能仍想使用间隔计时器定期更新当前值。同样,您需要检查要使用的变量的作用域是否正确,以便使用它们的函数可以看到它们,并且在函数调用之间不会丢失它们。