[javascript] JavaScript에서 잠금을 구현하는 방법

lockC # 과 동등한 것을 JavaScript에서 어떻게 구현할 수 있습니까?

그래서 제가 생각하는 간단한 사용 사례를 설명하려면 다음과 같습니다.

사용자가 버튼을 클릭합니다 B. Bonclick 이벤트를 발생시킵니다. 경우 Bevent-state이벤트 대기 위해 B에있을 ready-state전파하기 전에. 경우 Bready-state, B잠겨로 설정 event-state한 후, 이벤트 전파를. 이벤트 전파가 완료되면 B이로 설정됩니다 ready-state.

클래스를 추가하고 제거하는 것만으로 이것에 가까운 작업을 수행 할 수있는 방법을 알 수 있습니다. ready-state버튼 를 . 그러나 문제는 사용자가 변수를 설정할 수있는 것보다 빠르게 연속으로 두 번 버튼을 클릭 할 수 있으므로 일부 상황에서는 잠금 시도가 실패한다는 것입니다.

누구든지 JavaScript에서 실패하지 않는 잠금을 구현하는 방법을 알고 있습니까?



답변

잠금은 스레드가없고 동시성 보호가 필요하지 않은 JS에서 의심스러운 아이디어입니다. 지연된 실행에 대한 호출을 결합하려고합니다. 내가 따르는 패턴은 콜백을 사용하는 것입니다. 이 같은:

var functionLock = false;
var functionCallbacks = [];
var lockingFunction = function (callback) {
    if (functionLock) {
        functionCallbacks.push(callback);
    } else {
        $.longRunning(function(response) {
             while(functionCallbacks.length){
                 var thisCallback = functionCallbacks.pop();
                 thisCallback(response);
             }
        });
    }
}

DOM 이벤트 리스너 또는 pubsub 솔루션을 사용하여이를 구현할 수도 있습니다.


답변

JavaScript는 예외 ( XMLHttpRequest onreadystatechange일부 Firefox 버전의 핸들러)가 거의 없는 이벤트 루프 동시 . 따라서이 경우 잠금에 대해 걱정할 필요가 없습니다.

JavaScript에는 “이벤트 루프”를 기반으로하는 동시성 모델이 있습니다. 이 모델은 C 또는 Java와 같은 다른 언어의 모델과는 상당히 다릅니다.

JavaScript 런타임에는 처리 할 메시지 목록 인 메시지 큐가 포함됩니다. 각 메시지에는 기능이 연결되어 있습니다. 스택이 비어 있으면 큐에서 메시지를 가져와 처리합니다.처리는 관련 함수를 호출하여 초기 스택 프레임을 만드는 것으로 구성됩니다. 스택이 다시 비워지면 메시지 처리가 종료됩니다.

각 메시지는 다른 메시지가 처리되기 전에 완전히 처리됩니다. 이것은 함수가 실행될 때마다 선점 될 수없고 다른 코드가 실행되기 전에 완전히 실행된다는 사실을 포함하여 프로그램에 대해 추론 할 때 좋은 속성을 제공합니다 (그리고 함수가 조작하는 데이터를 수정할 수 있음). 예를 들어, 함수가 스레드에서 실행되는 경우 언제든지 중지되어 다른 스레드에서 다른 코드를 실행할 수있는 C와 다릅니다.

이 모델의 단점은 메시지를 완료하는 데 너무 오래 걸리면 웹 애플리케이션이 클릭 또는 스크롤과 같은 사용자 상호 작용을 처리 할 수 ​​없다는 것입니다. 브라우저는 “스크립트를 실행하는 데 너무 오래 걸립니다”대화 상자로이를 완화합니다. 따라야 할 좋은 방법은 메시지 처리를 짧게 만들고 가능하면 하나의 메시지를 여러 메시지로 줄이는 것입니다.

이벤트 루프 동시성에 대한 추가 링크는 E를 참조하십시오.


답변

나는 성공 뮤텍스 약속을했습니다 .

귀하의 경우 잠금이 필요하지 않을 수도 있다는 다른 답변에 동의합니다. 그러나 Javascript에서 잠금이 필요하지 않다는 것은 사실이 아닙니다. 동시성을 처리하지 않는 외부 리소스에 액세스 할 때는 상호 배타성이 필요합니다.


답변

잠금은 다중 스레드 시스템에 필요한 개념입니다. 작업자 스레드를 사용하더라도 작업자간에 메시지가 값별로 전송되므로 잠금이 필요하지 않습니다.

버튼 사이에 세마포어 (플래 깅 시스템)를 설정해야한다고 생각합니다.


답변

이벤트를 마친 후 버튼을 비활성화하고 활성화하지 않는 이유는 무엇입니까?

<input type="button" id="xx" onclick="checkEnableSubmit('true');yourFunction();">

<script type="text/javascript">

function checkEnableSubmit(status) {
  document.getElementById("xx").disabled = status;
}

function yourFunction(){

//add your functionality

checkEnableSubmit('false');
}

</script>

행복한 코딩 !!!


답변

내 경우에 따르면 JoshRiver의 답변에 추가되었습니다.

var functionCallbacks = [];
    var functionLock = false;
    var getData = function (url, callback) {
                   if (functionLock) {
                        functionCallbacks.push(callback);
                   } else {
                       functionLock = true;
                       functionCallbacks.push(callback);
                        $.getJSON(url, function (data) {
                            while (functionCallbacks.length) {
                                var thisCallback = functionCallbacks.pop();
                                thisCallback(data);
                            }
                            functionLock = false;
                        });
                    }
                };

// Usage
getData("api/orders",function(data){
    barChart(data);
});
getData("api/orders",function(data){
  lineChart(data);
});

단 하나의 api 호출이 있으며이 두 함수는 동일한 결과를 사용합니다.


답변

잠금은 여전히 ​​JS에서 사용됩니다. 내 경험상 나는 AJAX 호출을하는 요소를 클릭하는 스팸을 방지하기 위해 잠금을 사용하기 만하면되었다. AJAX 호출을 위해 설정된 로더가있는 경우이 작업은 필요하지 않습니다 (클릭 후 버튼 비활성화도 포함). 하지만 여기 어느 쪽이든 내가 잠금에 사용한 것입니다.

var LOCK_INDEX = [];
function LockCallback(key, action, manual) {
    if (LOCK_INDEX[key])
        return;
    LOCK_INDEX[key] = true;
    action(function () { delete LOCK_INDEX[key] });
    if (!manual)
        delete LOCK_INDEX[key];
}

용법:

수동 잠금 해제 (일반적으로 XHR 용)

LockCallback('someKey',(delCallback) => {
    //do stuff
    delCallback(); //Unlock method
}, true)

자동 잠금 해제

LockCallback('someKey',() => {
    //do stuff
})