2016-07-04 3 views
0

이전의 question을 약간 수정하면 정확한 사용 사례가 객체를 전달하는 위치 아래에 있는데,이 경우 가장 좋은 해결책은 무엇입니까?객체 유형 변수에 대한 클로저

Product.prototype.list = function(body) { 
    body.options = { 
     hostname: endPoints.product, 
     path: '/applications/' + body.entity.type, 
     method: 'GET' 
    }; 
    return remote.request(body) 
     .then(function(result){ 
      body[body.entity.type] = result; 
      return body; 
     }); 
}; 

var body = { 
    entity: { 
     type: null 
    } 
}; 

body.entity.type = "coke"; 
product.list(body) 
    .then(console.log); //will this have {coke: []} or {pepsi: []} 

body.entity.type = "pepsi"; 
product.list(body) 
    .then(console.log); 

개체 기반 참조를 사용할 때 작동하지 않습니다.이 경우 해결책은 무엇입니까?

+1

가장 좋은 해결책은 작동하는 것입니다. 작동합니까? 그렇다면 - 그것이 최상 *입니다. – zerkms

+0

아니요, 객체 기반 참조를 사용할 때 작동하지 않습니다 – user2727195

+0

여기 'endPoints.product'는 무엇입니까? –

답변

0

문제는 코드가 비동기입니다. 따라서, 어떤 일어나고있는 것은이 같은 것입니다 : 당신은 비동기 호출을 = "콜라"

    1. 당신은 설정 body.entity.type

    2. 당신은 설정 body.entity.type = 당신은 RU 또 다른 비동기 호출

    3. 통역사가 유휴 상태 (더 이상 자바 스크립트를 만들

    4. "펩시" n) 따라서 네트워킹 코드를 실행할 수 있습니다.

    5. 자바 스크립트 body.entity.type = "펩시"

    6. 자바 스크립트가 body.entity.type = "펩시"로 두 번째 네트워크 요청 하게 완전한

    7. 네트워크 요청을 첫 번째 네트워크 요청 한다 (처음 도착하는 에 따라 순서가 다를 수 있음) 콜백을 호출합니다.

    그래서 객체 참조이기 때문에 둘을 console.log는 "펩시"를해야합니다 그리고 당신은 모두의 요청에 같은 객체을 통과하고 있습니다. 그것은

    일반 객체와이 작품을 만들기 위해 수 :

    var body1 = { 
        entity: { 
         type: "coke" 
        } 
    }; 
    
    var body2 = { 
        entity: { 
         type: "pepsi" 
        } 
    }; 
    
    product.list(body1) 
        .then(console.log); 
    
    product.list(body2) 
        .then(console.log); 
    

    당신은 코드를 더 재사용 할 수 있도록, 하나 생성자 사용하려면 :

    function Body (type) { 
        this.entity = {type: type}; 
    } 
    
    product.list(new Body('pepsi')) 
        .then(console.log); 
    
    product.list(new Body('coke')) 
        .then(console.log); 
    

    을 또는 함수를 사용 객체 리터럴을 반환합니다.

    function makeBody (type) { 
        return {entity: {type: type}}; 
    } 
    
    product.list(makeBody('pepsi')) 
        .then(console.log); 
    
    product.list(makeBody('coke')) 
        .then(console.log); 
    

    단일 객체에 대한 전역 참조와 함수 내에서 만들어진 객체 사이의 차이점은 전자가 미래에 발생하기를 기다리는 두 이벤트 사이에 공유되는 하나의 객체이고 이후에는 두 개의 개별 객체가 두 개의 개별 이벤트에 전달된다는 점입니다.

  • +0

    계몽주의에 감사드립니다. 나는 목록 함수 내에서 이것을 수행 했습니까? 참조 된 객체로 delink하고 새로운 사본을 생성하려면, 이것을 대답에 추가하십시오. 기본적으로'body1'과'body2'가 밝혀졌습니다. body = JSON.parse (JSON.stringify (body));' 나 – user2727195

    +0

    JSON.stringify 및 구문 분석은 비쌉니다. 매번 새로운 객체 리터럴을 작성하는 함수를 작성하는 것이 좋습니다. 신속한 수정이 가능하지만 나중에 리팩터링 할 것입니다. – slebetman

    0

    약속 및 비동기 작업을 사용 중이므로 두 비동기 작업 모두 "항공편 중"입니다.

    그리고 자바 스크립트 개체는 복사가 아닌 포인터로 전달됩니다.따라서 비동기 작업에 개체를 전달하고 해당 비동기 작업에서 해당 개체를 사용/수정 한 다음 동일한 개체를 다른 비동기 작업으로 전달하면 해당 비동기 작업도 함께 사용되므로 두 가지 비동기 작업을 수행하면 동일한 개체를 사용하십시오.

    이와 같이 두 비동기 작업의 개별 타이밍을 기준으로 예측할 수없는 결과가 발생합니다. 마지막 비동기 작업이 완료되면 객체에 대한 마지막 수정이 이루어지며 이전에 완료된 비동기 작업을 덮어 씁니다.

    일반적인 해결책은 동일한 개체를 비동기 작업에 전달하거나 비동기 작업을 변경하여 전달 된 개체의 복사본을 만든 다음 복사본을 수정하고 반환하도록하는 것입니다. 각 비동기 작업에 다른 객체를 전달하거나 비동기 작업을 변경하여 전달 된 객체를 수정하지 않는 한 이러한 충돌을 피할 수 있습니다.

    요약하자면

    , 두 가지 솔루션은 :

    1. 각 비동기 작업에 동일한 개체를 전달하지 마십시오. 비동기 호출마다 새 객체를 만듭니다.
    2. 비동기 작업을 변경하여 전달 된 개체를 수정하지 않도록합니다. 개체 자체를 만들고 반환 할 수 있습니다.
    +0

    감사합니다.'body = JSON.parse (JSON.stringify (body))'함수를'list' 본문에서 사용했습니다. 값이 비쌉니까? – user2727195

    +0

    @ user2727195 - 다음은 [개체를 복제하는 가장 효율적인 방법은 무엇입니까?]에 대한 설명입니다 (http://stackoverflow.com/questions/122102/what-is-the-most-efficient-way-to-clone -객체). – jfriend00

    관련 문제