2012-12-17 2 views
1

두 가지 노드 서비스 호출이 있습니다. 하나는 LDAP 그룹에서 그룹 구성원을 얻고 다른 하나는 구성원 세부 정보를 얻는 것입니다. 각 호출은 콜백을 사용하여 차단되지 않으므로 때때로 레코드가 개인에 대해 검색된 세부 정보와 일치하지 않는 상황에 처하게됩니다.클라이언트에서 node.js 서비스를 호출 할 때 경쟁 조건이 발생했습니다.

경쟁 조건을 방지하기 위해 이것을 코드하는 영리한 방법이 있습니까? 때로는 작동하지만, 콘솔 로그를보고있는 라인에서 자주 반복되는 레코드가 저장소에서 반환 된 레코드와 일치하지 않아서 직원 세부 정보를 얻을 수 없습니다. 단일 스레드 환경에서

onGroupSelected: function (list, idx, el, record) { 
    var store = Ext.getStore('GroupMembers'); 
    store.getProxy().setUrl('http://people-nodejs.xxx.xxx.com/ldap/group/' + record.get('cn')); 
    var that = this; 
    store.load({ 
     callback: function (records, operation) { 
      var empstore = Ext.getStore('EmployeeDetails'); 
      Ext.each(records, function(rec, ndx) { 
       console.log(ndx + ":" + rec.get('memberUid')); 
       if (rec.get('isMember')) { 
        empstore.getProxy().setUrl('http://people-nodejs.xxx.xxx.com/ldap/user/' + rec.get('memberUid')); 
        empstore.load({ 
         callback: function(emps, op) { 
          console.log(ndx + ":" + rec.get('memberUid') + "--" + emps[0].get('fullName')); 
          rec.set('workforceID', emps[0].get('workforceID')); 
          rec.set('fullName', emps[0].get('fullName')); 
          that.getGroupMembersList().setRecord(rec); 
         } 
        }); 
       } 
      }); 
      // Remove empty records and populate with records from above 
      store.removeAll(); 
     } 
    }); 

답변

5

자바 스크립트 (및 Node.js를)처럼, 당신이 정말로 경쟁 조건을 가질 수 없습니다, 다음은 코드를 살펴입니다.

대신 중첩 된 함수 및 루프에서 변수가 작동하는 방식에 대해 자바 스크립트 클로저와 오해가 발생합니다.

rec

Ext.each(records, function(rec, ndx) 내부에 정의되며, 그것은 각각의 반복에 대해, rec가 아직 콜백이 실행되었을 때 같은 값에 바인딩한다는 가정하에, 값의의 콜백 함수 내에서, 당신이 사용하고 있습니다.

이것은 올바르지 않으며 대신에 rec의 값은 함수가 생성 될 때가 아니라 콜백 함수가 실행될 때 바인딩됩니다 (본질적으로 클로저의 정의입니다).

그래서 그 대신이 예상대로 작동하려면, 당신은 같은 수행하여, 작성시 준수 할 rec을 강제해야합니다 (참고 : 구문은 문제가있을 수 있습니다) :

callback: (function(myrec,index){ 
    return function(emps, op) { 
     console.log(index + ":" + myrec.get('memberUid') + "--" + emps[0].get('fullName')); 
     myrec.set('workforceID', emps[0].get('workforceID')); 
     myrec.set('fullName', emps[0].get('fullName')); 
     that.getGroupMembersList().setRecord(myrec); 
    };)(rec,ndx); 

을 예에서 위의 경우 익명의 javascript 함수를 즉시 실행하고 rec 값은 생성시 myrec에 바인딩됩니다. 익명 함수는 콜백과 동일한 서명을 가진 함수를 반환하고 콜백이 함수를 실행할 때 적절한 값을 갖습니다. rec

+0

브라우저 클라이언트는 노드에 대한 동시 호출을 수행 할 때 단일 스레드가 아닙니다. emps 세부 정보를위한 .js 서비스. 그래도 좋은 지적을 불러 일으킨다. 그러나 폐쇄를 수정 한 후에도이 변경 사항은 여전히 ​​사용자가 복제 된 동일한 결과를 산출합니다. : – occasl

+0

핸들러 내부에서 전역 변수를 사용하지 않는 한, 서버에 대한 각 클라이언트의 호출은 자체 스레드에서 실행되는 것처럼 노드에 의해 "자체 포함"되어야합니다. 다중 귀하의 서버 api에 대한 호출, 그럼 당신은 (아마도'onGroupSelected'을 호출하는 코드에서) 호출 스택에 대해 더 높은 클로저 관련 문제가 있다고 의심합니까? – Alan

+0

또는이 코드는 아마도 : var empstore = Ext.getStore ('EmployeeDetails')'Javascript의 이벤트 큐는 IO를 기다리기 전까지 (이벤트 큐에 다시 배치 될 때까지) 동 기적으로 실행됩니다. 그래서'empstore'가 동일한 사용자로 두 번로드 될 가능성이 있습니다. 이중 체크 솔루션을 사용합니다 본질적으로 empstore가로드하기 전에로드하려고하는 레코드를 이미 포함하고 있는지 확인하십시오. – Alan

관련 문제