문제

시나리오는 다음과 같습니다.

내 사용자는 기본적으로 스프레드 시트의 제거 버전으로 그리드가 제공됩니다. 그리드의 각 행에 텍스트 상자가 있습니다. 텍스트 상자에서 값을 변경하면 입력에 대한 유효성 검사를 수행하고 그리드를 구동하는 컬렉션을 업데이트하고 페이지의 하위 토탈을 다시 그리기하고 있습니다. 이것은 모두 각 텍스트 상자의 OnChange 이벤트에 의해 처리됩니다.

"저장"버튼을 클릭하면 버튼의 OnClick 이벤트를 사용하여 양에 대한 최종 유효성 검사를 수행 한 다음 전체 입력을 웹 서비스로 보내면 저장합니다.

적어도 양식을 제출 버튼으로 탭하면 발생합니다.

문제는 값을 입력 한 다음 즉시 저장 버튼을 클릭하여 userInputChanged ()가 완료되기 전에 SaveForm ()가 실행되기 시작한다는 것입니다. 내 코드는 settimeout을 사용하지 않지만 사용을 사용하여 느린 UserInputChanged 유효성 검사 코드를 시뮬레이션합니다.

 <!-- snip -->
 <script>
    var amount = null;
    var currentControl = null;

    function UserInputChanged(control) {
        currentControl = control;
        // use setTimeout to simulate slow validation code (production code does not use setTimeout)
        setTimeout("ValidateAmount()", 100); 
    }

    function SaveForm() {
        // call web service to save value
        document.getElementById("SavedAmount").innerHTML = amount;
    }

    function ValidateAmount() {
        // various validationey functions here
        amount = currentControl.value; // save value to collection
        document.getElementById("Subtotal").innerHTML = amount; // update subtotals

    }
</script>
<!-- snip -->
Amount: <input type="text" id="UserInputValue" onchange="UserInputChanged(this);" /> <br />
Subtotal: <span id="Subtotal"></span> <br />
<input type="button" onclick="SaveForm();" value="Save" /> <br /><br />
Saved amount: <span id="SavedAmount"></span>
<!-- snip -->

유효성 검사 코드의 속도를 높일 수는 없다고 생각합니다. 유효성 검사가 완료되기 전에 코드가 웹 서비스를 호출하려고 시도 할 정도로 느리게 느리게 진행됩니다.

내 컴퓨터에서 ~ 95ms는 저장 코드가 시작되기 전에 유효성 검사 코드가 실행되는지 간의 마법 번호입니다. 사용자의 컴퓨터 속도에 따라 높거나 낮을 수 있습니다.

이 조건을 처리하는 방법이 있습니까? 동료는 검증 코드가 실행되는 동안 세마포어를 사용하고 세이브 코드의 바쁜 루프를 사용하여 세마포어가 잠금 해제 될 때까지 대기 할 것을 제안했지만 코드에 바쁜 루프를 사용하지 않으려 고합니다.

도움이 되었습니까?

해결책

세마포어를 사용하십시오 (StillnedSvalidating이라고 부르겠습니다). SaveForm 함수가 StillneDSvalidating 세마포어가 Up이라는 것을 보는 경우, 자체의 두 번째 세마포어를 활성화하고 (여기서 FormneedSsaving이라고 부르 겠음) Return을 활성화하십시오. 유효성 검사 함수가 완료되면 FormneedSsaving 세마포어가 UP이면 SaveForm 함수를 자체적으로 호출합니다.

jankcode에서;

function UserInputChanged(control) {
    StillNeedsValidating = true;
    // do validation
    StillNeedsValidating = false;
    if (FormNeedsSaving) saveForm(); 
}

function SaveForm() {
    if (StillNeedsValidating) { FormNeedsSaving=true; return; }
    // call web service to save value
    FormNeedsSaving = false;
}

다른 팁

유효성 검사 중에 저장 버튼을 비활성화합니다. 가장 먼저 유효성 검사가 발생하는대로 비활성화 된 것으로 설정하고 완료 할 때 다시 활성화하십시오.

예를 들어

function UserInputChanged(control) {
    // --> disable button here --< 
    currentControl = control;
    // use setTimeout to simulate slow validation code (production code does not use setTimeout)
    setTimeout("ValidateAmount()", 100); 
}

그리고

function ValidateAmount() {
    // various validationey functions here
    amount = currentControl.value; // save value to collection
    document.getElementById("Subtotal").innerHTML = amount; // update subtotals
    // --> enable button here if validation passes --<
}

설정 타임 아웃을 제거하고 유효성 검사를 하나의 기능을 수행 할 때 조정해야하지만 사용자가 초인간 반사 신경이 없으면 가야합니다.

타임 아웃이 문제를 일으키고 있다고 생각합니다 ... 만약 그것이 일반 코드 (비동기 Ajax 호출, 타임 아웃 등이 없음)가 될 경우 userinputchanged가 완료되기 전에 SaveForm이 실행될 것이라고 생각하지 않습니다.

세마포어 또는 뮤트는 아마도 가장 좋은 방법 일 것입니다. 그러나 바쁜 루프 대신에 setTimeout() 스레드 수면을 시뮬레이션합니다. 이와 같이:

busy = false;

function UserInputChanged(control) {
    busy = true;
    currentControl = control;
    // use setTimeout to simulate slow validation code (production code does not use setTimeout)
    setTimeout("ValidateAmount()", 100); 
}

function SaveForm() {
    if(busy) 
    {
       setTimeout("SaveForm()", 10);
       return;
    }

    // call web service to save value
    document.getElementById("SavedAmount").innerHTML = amount;
}

function ValidateAmount() {
    // various validationey functions here
    amount = currentControl.value; // save value to collection
    document.getElementById("Subtotal").innerHTML = amount; // update subtotals
    busy = false;
}

전체 그리드의 상태를 모니터링하는 반복 기능을 설정하고 전체 그리드가 유효한지 여부를 나타내는 이벤트를 제기 할 수 있습니다.

그런 다음 '양식 제출'버튼은 해당 상태에 따라 스스로를 활성화하거나 비활성화합니다.

오, 지금 비슷한 반응을 보았습니다. 물론 그게 작동합니다.

Async 데이터 소스로 작업 할 때 JavaScript 프로세스 스레드는 원격 데이터 소스에서 아직 반환되지 않은 데이터에 의존 할 수있는 지침을 계속 실행하기 때문에 레이스 조건을 확실히 가질 수 있습니다. 그렇기 때문에 콜백 함수가 있습니다.

예에서 유효성 검사 코드로의 호출에는 유효성 검사가 반환 될 때 무언가를 수행 할 수있는 콜백 함수가 있어야합니다.

그러나 복잡한 논리로 무언가를 만들거나 기존 일련의 콜백을 문제를 해결하거나 향상 시키려고 할 때는 미칠 수 있습니다.

그것이 제가 Proto-Q 라이브러리를 만든 이유입니다. http://code.google.com/p/proto-q/

이러한 유형의 작업을 많이하면 확인하십시오.

Race 조건이없고 JavaScript가 단일 스레드이므로 JavaScript에서 레이스 조건이 발생할 수 없으므로 2 개의 스레드는 서로 방해 할 수 없습니다.

당신이주는 예는 아주 좋은 예가 아닙니다. Settimeout 호출은 호출 된 함수를 JavaScript 엔진의 대기열에 놓고 나중에 실행합니다. 이 시점에서 저장 버튼을 클릭하면 저장이 완전히 완료된 후 설정 타임 아웃 함수가 호출되지 않습니다.

JavaScript에서 발생하는 것은 OnChange 이벤트가 호출되기 전에 OnClick 이벤트가 JavaScript 엔진으로 호출된다는 것입니다.

JavaScript 디버거 (FireBug, Microsoft ScreaPt Debugger)를 사용하지 않는 한 JavaScript가 단일 스레드입니다. 그 프로그램은 스레드를 가로 채고 일시 중지합니다. 다른 스레드의 해당 시점부터 (이벤트, Settimeout 통화 또는 XMLHTTP 핸들러)를 통해 실행할 수 있으므로 JavaScript가 동시에 여러 스레드를 실행할 수 있습니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top