Синтаксис JavaScript Scoping and Closure
У меня проблемы с областью видимости и закрытием в фрагменте JavaScript. Я пытаюсь обновить оба class
а также onclick
свойства кнопки. В основном это должно переключаться между "Высоким" и "Низким". Я мог заставить функцию выполняться без попыток изменить параметры, но она не была успешно обновлена. Итак, я попытался изменить его в код ниже, и теперь я получаю сообщение об ошибке channel
не определено. Может кто-нибудь помочь мне с синтаксисом здесь? Мне нужна внутренняя функция, чтобы можно было оценить как канал, так и значение.
Я знаю, что предоставленный код не будет работать из-за асинхронного обратного вызова. Я просто не могу получить правильный синтаксис для onreadystatechange
функция. Пожалуйста, дайте мне знать, если я смогу дать какие-либо дополнительные разъяснения по поводу моей проблемы. Благодарю.
function setDio(channel, value) {
var xmlhttp = new XMLHttpRequest();
xmlhttp.onreadystatechange = (function(channel,value) { return function(){
if (this.readyState === 4)
{
if (this.status === 200) {
document.getElementById('ok-msg').innerHTML = 'Digital Output successfully set to '+value+'.';
document.getElementById('ok-alert').style.display = 'block';
if(value===1)
{
document.getElementById('dio'+channel+'-high').class = 'ibradioactive';
document.getElementById('dio'+channel+'-low').class = 'ibradioinactive';
document.getElementById('dio'+channel+'-low').onclick = function(){ setDio(channel,0);};;
document.getElementById('dio'+channel+'-high').onclick = function(){} ;;
}
else
{
document.getElementById('dio'+channel+'-high').class = 'ibradioinactive';
document.getElementById('dio'+channel+'-low').class = 'ibradioactive';
document.getElementById('dio'+channel+'-high').onclick = function(){ setDio(channel,1);};;
document.getElementById('dio'+channel+'-low').onclick = function(){} ;;
}
}
else
{
document.getElementById('error-msg').innerHTML = 'Digital Output set failed ('+ this.status +'): '+this.responseText;
document.getElementById('error-alert').style.display = 'block';
}
}
};})(channel,value);
xmlhttp.open('POST', '/dio/' + channel, true);
xmlhttp.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
xmlhttp.send('dio-value=' + value);
}
.alert,.ok-alert,.error-alert,.info-alert,.warning-alert {
font-family:arial;
font-weight:700;
color:#FFF;
margin-bottom:15px;
border-radius:20px;
padding:20px;
display:none;
}
.ok-alert {
background-color:#4CAF50;
}
.error-alert {
background-color:#f44336;
}
.info-alert {
background-color:#2196F3;
}
.warning-alert {
background-color:#ff9800;
}
.alert-close {
margin-left:15px;
color:#FFF;
font-weight:700;
float:right;
font-size:22px;
line-height:20px;
cursor:pointer;
transition:.3s;
}
.inner-group {
display:inline-block;
border:0 solid #000;
font-family:arial;
font-weight:700;
font-size:12pt;
background:#ccc;
border-radius:15px;
vertical-align:text-top;
box-shadow:4px 4px 10px #66a;
margin:10px;
padding:10px 4px;
transition:1s;
}
.ibradioactive {
background:#11AF11;
}
.ibradioactive span {
color:#fff;
}
.ibradioinactive span {
color:#000;
}
.ibradioinactive {
background:#ddd;
}
.ibradioinactive:hover {
background-color:#acf;
}
.ibradio,.ibradioactive,.ibradioinactive {
width:50px;
height:50px;
cursor:pointer;
box-shadow:3px 3px 2px #000;
-webkit-box-shadow:3px 3px 2px #000;
-moz-box-shadow:3px 3px 2px #000;
font-weight:700;
color:#000;
border-radius:40px;
border:1px solid #999;
margin:10px 10px 10px 20px;
padding:5px;
}
label {
display:inline-block;
width:125px;
padding:3px 10px;
}
<div id="error-alert" class="error-alert">
<span class="alert-close" onclick="this.parentElement.style.display='none';">×</span>
<span id="error-msg">This is an error alert box.</span>
</div>
<div id="ok-alert" class="ok-alert">
<span class="alert-close" onclick="this.parentElement.style.display='none';">×</span>
<span id="ok-msg">This is a success alert box.</span>
</div>
<div id="info-alert" class="info-alert">
<span class="alert-close" onclick="this.parentElement.style.display='none';">×</span>
<span id="info-msg">This is an info alert box.</span>
</div>
<div id="warning-alert" class="warning-alert">
<span class="alert-close" onclick="this.parentElement.style.display='none';">×</span>
<span id="warning-msg">This is an warning alert box.</span>
</div>
<br />
<div class="inner-group" style="width:550px;">
<label class="l2">Digital I/O #1</label><br>
<label class="l2" style="width:175px">Mode: OUTPUT</label><br />
<label class="l2">New State:</label>
<button class ="ibradioactive" type="submit" id="dio1-high" name="dio1-high" onclick="setDio(1,1)"><span>HIGH</span></button>
<button class ="ibradioinactive" type="submit" id="dio1-low" name="dio1-low" onclick="setDio(1,0)"><span>LOW</span></button>
</div>
РЕДАКТИРОВАТЬ:
Вот упрощенная версия моего исходного кода, который не работал:
function setDio(channel, value) {
var xmlhttp = new XMLHttpRequest();
xmlhttp.onreadystatechange = function() {
if (this.readyState === 4)
{
if (this.status === 200) {
if(value === 1)
{
document.getElementById('dio'+channel+'-high').class = 'ibradioactive';
document.getElementById('dio'+channel+'-low').class = 'ibradioinactive';
}
else
{
document.getElementById('dio'+channel+'-high').class = 'ibradioinactive';
document.getElementById('dio'+channel+'-low').class = 'ibradioactive';
}
}
}
};
xmlhttp.open('POST', '/dio/' + channel, true);
xmlhttp.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
xmlhttp.send('dio-value=' + value);
}
Поскольку это не сработало, я попытался изменить область видимости и добавить замыкание, чтобы убедиться, что функция оценивает значения параметров, которые использовались во время вызова, вместо выбора значений по умолчанию.
Классы не менялись, как ожидалось, и, фактически, асинхронный запрос фактически не принимался сервером. Итак, кто-нибудь может понять, почему эта функция не работает должным образом? У меня есть похожие функции, которые просто обновляют просто innerHTML
значения успешно. Изменение класса, однако, похоже, не работает.
РЕДАКТИРОВАТЬ 2:
Итак, я обнаружил часть своей проблемы. Причина, по которой класс не менялся, в том, что я пытался установить class
с текстом вместо объекта. Изменение на className
кажется, прояснил это. Я также вернулся к тому, чтобы не использовать дополнительную область видимости замыкания, и теперь она может работать правильно. Все еще делаю тестирование, чтобы проверить все изменения.
1 ответ
Я не уверен, почему существует необходимость в явном закрытии, определенном..
xmlhttp.onreadystatechange = function() {
console.log(channel); // parent function parameter can still be accessed here.
}