2013-02-12 3 views
-1

JS/jQuery에 구현 된 응용 프로그램에 상태 값 사전을 제공하려고합니다. 값은 서버 (ajax)에서 가져와야합니다. 비동기 방식으로이를 수행하여 초기화 중에 해당 요청을 시작할 수 있습니다. 값에 대한 실제 액세스는 나중에 코드를 쉽게 이해할 수 있도록 동기화되어야합니다. (많이) 단순화 된 코드는 현재 다음과 같습니다비동기 요청으로 채워진 구조에 동기식 액세스

초기화 :

$(document).ready(function(){ 
    Status.fetch(); 
}) 

구조 : (작동) 아약스 호출에 의해 작성

Status:{ 
    Valid:new $.Deferred(), 
    Server:{}, 
    /* ... */ 
    fetch:function(){ 
     if (Status.Valid.isResolved()){ 
      // status already present due to a past request 
      return Status.Valid.promise(); 
     }else{ 
      // fetch status information from server 
      $.ajax({ 
       type:  'GET', 
       url:  'status.php'), 
       cache: true, 
       dataType: 'json' 
      }).done(function(response){ 
       $.each(response,function(key,val){ 
        Status.Server[key]=val; 
       }); 
       Status.Valid.resolve(Status.Server); 
      }).fail(function(response){ 
       Status.Valid.reject(NaN); 
      }); 
      return Status.Valid.promise(); 
     } 
    }, // Status.fetch 
    getServerAspect:function(aspect){ 
     $.when(
      Status.fetch() 
     ).done(function(server){ 
      return server[aspect]; 
     }).fail(function(server){ 
      return NaN; 
     }) 
     /* whyever: processing always comes here, which I don't understand... */ 
    }, // Status.getServerAspect 
} // Status 

Status.Server 가져옵니다. Status.getServerAspect()Status.Server 구조 (은 아니요,이 아님) 내에 저장된 애스펙트에 대한 동시 액세스를 허용하는 방법의 한 예입니다.

기본 아이디어는 구조체에 액세스하기 전에 구조체의 비동기식 채우기가 실행된다는 것입니다. 모든 (동기식) 액세스는 해당 값이 나타날 때까지 참조 된 부분을 즉시 반환하거나 차단합니다. 그러나 어떤 스타일이든지 내에서 Status.getServerAspect()을 시도해도 메소드는 호출 범위에서 사용할 수있는 애스펙트 값없이 즉시 반환됩니다.

지연된 개체로 작업하는 기본 개념을 이해하는 것은 분명히 문제가 있습니다. 나는 항상 동기 처리를 위해 그것들을 사용하고, 매력처럼 작동한다. 그러나 이는 애플리케이션 전반에 걸쳐 비동기식 스타일을 사용해야한다는 것을 의미합니다.

if ('somevalue'==Status.getServerAspect('someaspect')) 
    ...do something... 

동기 및 비동기 처리 사이에 '다리'를 구축 할 수있는 트릭은 무엇입니까 : 조건식 간단한 유지되도록이 특별한 기능을 위해 나는, 동기 스타일을 선호?

+0

데이터가있을 때까지 무엇을 "차단"합니까? 내가 아는 한, 그건 아약스 동기화를하지 않는 현대의 브라우저에서는 불가능합니다. –

+0

@KevinB 비동기 가져 오기 프로세스에 의해 해결되는 지연된 객체를 사용하려고합니다. 나중에'지연된 객체를 사용하여'$ .when' 내부에서 평가함으로써 접근을 차단하려고합니다. 적어도 그 생각은 ... – arkascha

+0

맞습니다. '.done()'콜백에서 데이터를 반환 할 수 없습니다. –

답변

-2

내가 마지막으로 찾은 해결책을 공유하고 싶습니다. 그것은 우아한 것이 아니지만 그럼에도 불구하고 그것은 원래의 질문에 긍정적 인 방식으로 대답합니다. 따라서 요청에 따라 비동기 및 동기 액세스 조합을위한 접근 방식을 제공합니다.

다른 모든 기여자가 이것이 가능하지 않다고 주장 했으므로이 대답을 추가하는 것이 합리적이라고 생각합니다.

요청 된 값이 비동기 적으로 검색된 데이터 구조를 사용할 수있을 때만 리턴되도록 차단 루틴을 구현하는 것이 전부입니다. 그래서 결국 그냥 단순히 '대기'전략 여기에 마법 :

getServerAspect:function(aspect){ 
    /* the state of the asynchronous retrieval attempt */ 
    var resolution=Status.Valid.state(); 
    while ("pending"==resolution) { 
     setTimeout(function(){resolution=Status.Valid.state();},500); 
    } 
    /* asynchronous retrieval has finished */ 
    if ("resolved"==resolution){ 
     /* return vaule should be available */ 
     return server[aspect]; 
    }else{ 
     /* data could not be retrieved, something is borked */ 
     return NaN; 
    } 
}, // Status.getServerAspect 

[내 실제 솔루션은 더 복잡하기 때문에이 기능은, simplyfied 메모리에서 기록됩니다. ]

사실이 기능은 해상도를 기다리는 동안 GUI를 차단합니다. 이것은 우아하고 사실이 아니지만 원본에서 차단 동작이 명시 적으로 요구된다는 점에 유의하십시오. 정상적인 상황에서 검색은 서버 측면이 요청되기 전에 오랫동안 완료되어야하므로 "정상적으로"차단이 없습니다. 그리고이 상황이 아닌 경우, 비동기 처리에서도 최종 작업이 검색이 완료 될 때까지 지연되기 때문에 0.5 초를 기다리는 것이 좋습니다.

이 차단 전략을 사용하면 익명의 함수를 항상 사용할 필요가 없기 때문에 나머지 코드를 훨씬 간단하고 읽기 쉽게 유지할 수 있습니다. (비동기 동안) 단지 확실하게에서는 setTimeout (...) 호출로,

if ("expected"==Status.getServerAspect('someaspect')){ 
    /* do something */ 
} 
+0

'setTimeout'도 비동기입니다. 그게 작동 차단 솔루션이라고 생각하지 않습니다. 그리고 바쁜 기다림은 낙담합니다. – Bergi

-1

는 다음에, $.ajax 요청에 당신은 참 또는 거짓으로 async 속성을 설정할 수 있습니다, 또는 함수에 전달할

 $.when(
    Status.fetch(true) 

 Status:{ 
      Valid:new $.Deferred(), 
      Server:{}, 
      /* ... */ 
      fetch:function(asyncType){  /// boolean passed as param 
      if (Status.Valid.isResolved()){ 
      // status already present due to a past request 
      return Status.Valid.promise(); 
      }else{ 
      // fetch status information from server 
     $.ajax({ 
      type:  'GET', 
      url:  'status.php'), 
      cache: true, 
      dataType: 'json', 
      async: asyncType /////// will be true or false 
     }).done(function(response){ 
      $.each(response,function(key,val){ 
       Status.Server[key]=val; 
      }); 
      Status.Valid.resolve(Status.Server); 
     }).fail(function(response){ 
      Status.Valid.reject(NaN); 
     }); 
+0

하지만 아약스 요청이 동기가되는 것을 원하지 않습니다. 초기화하는 동안 트리거되어야하며 시간이 걸립니다. – arkascha

+0

false로 설정하면 시간이 걸릴 것이고 그 외의 작업은 완료 될 때까지 실행되지 않습니다. – CR41G14

+0

@ CR41G14 async : false는 사용자 경험에 영향을주는 웹 작업자 외부의 매우 나쁜 습관입니다. –

0

아래 참조 getServerAspect 단순히 약속을 반환합니다 그걸 써.

getServerAspect: function(){ 
    return Status.Valid.promise(); 
} 

지금 당신이 그것을 사용할 수 있습니다

Status.getServerAspect().done(function(data){ 
    if (data.someaspect == 'somevalue') { 
     // do something, but don't return! 
    } 
}) 

이 코드가 어떻게 작동하는지 비동기입니다.

함수 뒤에 이것을 추상화 할 수도 있지만 읽는 것이 더 어렵습니다. 지금

Status.getServerAspect: function(aspect,callback){ 
    Status.Valid.promise().done(function(data){ 
     callback(data[aspect]); 
    }) 
} 

당신은 그것을 좋아 사용할 수 있습니다

Status.getServerAspect('someaspect',function(value) { 
    if ('somevalue' == value) { 
     // do something but don't return! 
    } 
}); 
+0

물론, 이것은 내가 보통하는 일이다 (나는 그것을 썼다). 하지만 이로 인해 조건이 복잡해지고 오류가 발생하기 쉽습니다. 그 비동기 문장에서 조건문을 깨끗하게 유지할 수있는 솔루션을 찾고 있습니다. 내 생각은 그 비동기 물건을 'wrapper'메소드로 옮기는 것이었다. 그러나 어떻게? – arkascha

+0

물론 그렇지만 여전히 동일한 양식을 사용하려고합니다. 어쩌면 조금 더 열심히 읽을 수도 있습니다. –

+0

물론 포장지 안에 들어 있으므로 신경 쓰지 않을 것입니다. 그것은 래퍼가 아닌 celan이고 쉬워야하는 조건입니다. – arkascha

0

그것은이 asynchronyous 과정을 호출하고, 가장 쉬운 방법은이 개 부분에 기능을 분할하는 것이 synchronyous 만들려고 어렵다; 하나는 비동기 호출 전에 하나는 하나.

내가 찾은 최선의 방법은 약속 패턴을 사용하는 것입니다 또는 당신은 당신의 프로세스의 모든 단계에 의해 트리거 될 중재자를 시도하고 그것을 일련의 이벤트를 전달할 수 :

Good pattern to use for multiple xmlhttprequests used by different processes

자바 스크립트를하지 않습니다 내가 아는 한 실제로는 잠시 멈추거나 다른 언어처럼 기다릴 수있는 기능이 있습니다.

1

이 작동 그 Status.Valid.state(); 대신 단순히 간단한 조건문의 값에 액세스 할 수 있습니다 전화는 자주 수행되지 않습니다. 스레드를 차단할뿐만 아니라 WebWorker 외부에서 실행해서는 안되며 CPU에서 유휴 시간을 훔치기도합니다. 사실,이 접근법을 사용하는 대신 동기식 AJAX 요청을하는 것이 더 나은 해결책입니다. 발신자를 차단하는 동안 바쁜 대기가되지 않습니다. 그러나 가능한 경우 순전히 비동기 구현을 수행해야합니다.

관련 문제