2012-11-06 5 views
2

개체 배열을 만든 다음 배열 내에서 개체 속성에 액세스하려고 시도하지만 정의되지 않은 상태로 되돌아옵니다. createObjArray() 함수를 호출하고 console.log (objArray [1])를 수행 한 직후에 호출합니다. 그리고 모든 것을 가진 객체를 출력합니다 ... 속성은 훌륭합니다. 그러나, 나는 console.log (objArray [1] .name); 방화 광구가 "정의되지 않음"을 인쇄합니다. 또한 방화 광에서 코드를 실행하면 objArray [1] .name 위로 마우스를 가져 가면 올바른 이름이 표시됩니다. 여기 무슨 일이 일어나고 있니?개체가 배열 내에있을 때 개체 속성 액세스 (javascript)

var objArray = []; 

function createObjectArray(numOfObjs) { 

    for(var i=0; i<numOfObjs; i++) { 

packages.push(initObj(i)); 

    } 
} 

function initObj(i){ 
    var newPackage; 
    var p = {}; 
    $.getJSON('.../package' + i + '.json', function(data) { 
     newPackage = new Package(data); 
     p.name = newPackage.name; 
     p.id = i;  
    }); 
    return p; 
} 
+1

$ .getJSON이 비동기 호출을하고 있습니까? 그렇다면 initObj 메소드가 리턴 될 때 p는 비게됩니다. –

+0

console.log (arrayObj [1])를 사용하여 객체를 올바르게 인쇄합니다. 다음과 같이 전체 객체를 인쇄합니다 : Object {name = "my name", id = 1}. 그래서 P는 – user1804588

+0

을 두 번 게시합니다. 죄송합니다. – user1804588

답변

0

$ .getJSON에 대한 호출이 비동기입니다. initObj()가 p를 반환하면 여전히 빈 객체입니다.

그러나 initObj()는 $ .getJSON이 p가 채워질 때 p에 대한 참조를 캡처하는 클로저를 만듭니다.

이 때문에 배열을 채운 직후에 실행하는 코드에서 개체가 비어있는 것처럼 보입니다. 그러나 콘솔 명령을 실행하면 비동기 호출이 반환되고 개체가 채워집니다.

배열 작업을 계속하기 전에 모든 비동기 호출이 반환 될 때까지 기다려야합니다. 이를 수행하는 한 가지 방법은 호출을 할 때 카운터를 증가시키고 호출이 반환 될 때 카운터를 증가시킨 다음 마지막 호출이 반환 될 때 카운터가 0으로 떨어지고 처리를 계속하는 것입니다.

또는 배열의 모든 항목이 채워 졌을 때 배열을 폴링하도록 setTimout 루프를 설정할 수도 있습니다.

하나의 호출이 실패 할 수 있다고 생각하면 두 방법 모두 위험합니다. 그러나 여러 번의 실패를 처리 할 수 ​​있도록 여러 번의 ajax 호출을 할 때 근본적으로 위험합니다. 한 번에 모든 데이터를 가져 오는 것이 훨씬 더 깔끔할 것이므로 jQuery.ajax의 성공/오류 처리기에서 성공/오류 상태를 한 번 처리 할 수 ​​있습니다.

+0

배열을 작동시키는 $ .getJSON 뒤에 함수를 호출하려고 시도합니다. 고맙습니다! – user1804588

+0

편집 내용을 읽으십시오. 고마워, 나는 이것을 올바른 방법으로하는 방법을 조사해야 할 것이다. – user1804588

1

이 작동합니다 :

var objArray = []; 

function createObjectArray(numOfObjs, callback) { 
    var filledPackage = []; 
    var nbLeft = numOfObjs; 
    for(var i=0; i<numOfObjs; i++) { 
     initObj(i, function(p){ 
      filledPackage.push(p); 
      nbLeft--; 
      if (nbLeft === 0){ 
       callback(filledPackage); 
      } 
     }); 
    } 
} 

function initObj(i, callback){ 
    var newPackage; 
    var p = {}; 
    $.getJSON('.../package' + i + '.json', function(data) { 
     newPackage = new Package(data); 
     p.name = newPackage.name; 
     p.id = i;  
     callback(p); 
    }); 
} 

//Get a filled object array: 
createObjectArray(5, function(filledArray){ 
    objArray = filledArray; 
    //Code here will be executed AFTER all the $.getJSON queries have returned. 
    //objArray is not empty. 
}); 
//Code here will be executed WHILE the getJSON queries are running and 
//while objArray is still empty. Due to the way the JS event loop works, 
//it is impossible that code placed here will be able to use the content 
//of objArray unless you call an async function such as anything AJAX or 
//setTimeout, but that's iffy. Code you want to be executed once objArray 
//has been filled should be inside of the callback above. 

문제는 $ .getJSON이 자동으로 결과를 반환하지 않는 것을 의미 aynchronous 것입니다. 대신 콜백을 지정합니다. 콜백은 결과를 받으면 실행하는 함수입니다. 이 경우 콜백은 $ .getJSON을 호출 할 때 생성 된 익명 함수입니다. 콜백은 서버에서 결과를 받아서 배열에 추가 한 다음 배열이 채워 졌는지 검사합니다. $ .getJSON 함수로 인해 비동기 코드를 수행하므로 비동기 적으로 결과를 반환해야합니다. 그렇게하기 위해 우리는 initObj 함수가 완료되면 (다른 콜백) 호출 할 함수를 수신 할 것을 요구합니다. 콜백을 호출하고 매개 변수를 전달합니다. 그런 다음 콜백을 통해 채워진 배열을 다시 반환합니다.

관련 문제