2013-12-23 2 views
1

Dojo 상점의 경우 특정 코드를 put()add()으로 실행하고 싶습니다. 나는 데 문제는 JSON REST 저장을 위해, JsonRest.js에 add()put()를 호출 단지 함수이다 : 나는 add()aspect.around()를 사용하는 경우, 그래서aspect.around를 사용하고 있지만 서로를 호출하는 메소드를 확인하십시오.

add: function(object, options){ 
    options = options || {}; 
    options.overwrite = false; 
    return this.put(object, options); 
}, 

, 내 코드는 두 번 실행되는 끝 IFadd()을 스텁으로 구현하는 상점에서 생성 된 상점에 put()으로 코드를 적용합니다.

대부분의 상점에서 그렇게 할 것임을 알고 있습니다. 메서드가 중첩되어 있는지 여부와 상관없이 내 솔루션이 스토어와 작동하도록 보장하기 만하면됩니다.

Dojo 자신의 Observable.js에 동일한 문제가 있습니다.

function whenFinished(method, action){ 
    var original = store[method]; 
    if(original){ 
     store[method] = function(value){ 
     if(inMethod){ 
      // if one method calls another (like add() calling put()) we don't want two events 
      return original.apply(this, arguments); 
     } 
     inMethod = true; 
     try{ 
      var results = original.apply(this, arguments); 
      Deferred.when(results, function(results){ 
      action((typeof results == "object" && results) || value); 
      }); 
      return results; 
     }finally{ 
      inMethod = false; 
     } 
     }; 
    } 
    } 
    // monitor for updates by listening to these methods 
    whenFinished("put", function(object){ 
    store.notify(object, store.getIdentity(object)); 
    }); 


    whenFinished("add", function(object){ 
    store.notify(object); 
    }); 
    whenFinished("remove", function(id){ 
    store.notify(undefined, id); 
    }); 

내 질문은 : 그것은 방법 내에 있는지 확인하도록 기존 코드를 변경하고, 두 번 코드를 실행하지 않도록하는 간단한, "짧은"방법이이 그들이 그것을 다루는 방법입니까?

나는 그것을 줬다. 그러나 나는 clanky, hacky code로 끝났다. 내가 뭔가를 놓친 거지 확신 ... 여기

기존 코드입니다 : 이것은 내 시도가 ...

topic.subscribe('hotplate/hotDojoStores/newStore', function(storeName, store){ 

    aspect.around(store, 'put', function(put){ 

    return function(object, options){ 

     return when(put.call(store, object, options)).then(function(r) { 
     var eventName; 
     var identity = store.idProperty; 
     eventName = object[ identity ] ? 'storeRecordUpdate' : 'storeRecordCreate'; 

     topic.publish(eventName, null, { type: eventName, storeName: storeName, objectId: r[ identity ], object: object }, false); 

     }); 

    } 
    }); 

    aspect.around(store, 'add', function(add){ 
    return function(object, options){ 

     return when(add.call(store, object, options)).then(function(r) { 

     var identity = store.idProperty; 

     topic.publish('storeRecordCreate', null, { storeName: storeName, storeTarget: storeTarget, objectId: r[identity], object: object }, false } ); 

     }); 
    } 
    }); 
}); 
+0

나는 곡물을 따라 Observable이 내 저장소 랩퍼에서하는 일을 수행합니다. [put caller is add]를 확인하여 "더 짧은"접근 방식이있을 수 있습니다 (http://stackoverflow.com/questions/280389/how-do-you-find-out-the-caller-function-in-javascript) -하지만 피곤하고 그것을 방지하는 측면 때문에 스택 체조 선수가 필요할 수도 있습니다. – bishop

+0

아내가 내가 바라던 대답이 아니었다 ... 나의 시도 된 답을 볼 수 있니? 그것은 제정신이 아닌가요? – Merc

답변

0

이다는 내 시도는 그것의 여부에 대해 정말 "GET"하지 않는 무엇 100 % 안전 여부.

store.add()하면 두 번 연속이라고한다은 inMethod 첫 번째 호출에 의해 true로 설정되어 있는지 혹시 가능하며, 두 번째 add() 호출은 다음 첫 번째가에 관리하지 않았기 때문에 이미 true로 설정 발견 한 아직 거짓으로 설정 했습니까?

nextTick()이 내가 호출하는 두 개의 호출 사이에서 호출되는 경우에만 가능합니다.

아니면 완전히 혼란 스럽습니까? (매우 가능합니다 ...)

topic.subscribe('hotplate/hotDojoStores/newStore', function(storeName, store){ 

    var inMethod; 

    aspect.around(store, 'put', function(put){ 

     return function(object, options){ 

     if(inMethod){ 
      return when(put.call(store, object, options)); 
     } else { 

      inMethod = true; 

      try { 
      return when(put.call(store, object, options)).then(function(r) { 
       var eventName; 
       var identity = store.idProperty; 
       eventName = object[ identity ] ? 'storeRecordUpdate' : 'storeRecordCreate'; 

       topic.publish(eventName, null, { type: eventName, storeName: storeName, objectId: r[ identity ], object: object }, false); 

      }); 
      } finally { 
      inMethod = false; 
      } 

     } 

     } 
    }); 

    aspect.around(store, 'add', function(add){ 
     return function(object, options){ 

     if(inMethod){ 
      return when(add.call(store, object, options)); 
     } else { 

      inMethod = true; 

      try { 

      return when(add.call(store, object, options)).then(function(r) { 

       var identity = store.idProperty; 

       topic.publish('storeRecordCreate', null, { type: 'storeRecordCreate', storeName: storeName, objectId: r[identity], object: object }, false); 

      }); 
      } finally { 
      inMethod = false; 
      } 
     } 
     } 

    }); 

    aspect.around(store, 'remove', function(remove){ 
     return function(objectId, options){ 

     return when(remove.call(store, objectId, options)).then(function(r) { 

      topic.publish('storeRecordRemove', null, { type: 'storeRecordRemove', storeName: storeName, objectId: objectId }, false); 

     }); 
     }; 
    }); 

    }); 
+1

2 개의 add()가 back to back 인 경우, 같은 스택에있어 동일한 이벤트 루프가되어, 인터리브되지 않습니다. 시도에서의 반환은 약속이 해결 될 때까지 완료 할 수 없으므로 (.then) Promise 스태킹을 방지합니다. 따라서 코드가 안전하다고 판단되는데, Observable이 설립 한 whenFinished() 패턴을 리팩터링하지 않으시겠습니까? 내가 말할 수있는 것부터 유일한 확장은 메서드가 끝난 후에도 항목을 게시하는 것입니다. – bishop

+0

Dojo는 바퀴를 발명하기보다는 Dojo를 사용합니다. Dojo는'aspect '를 제공합니다. 그래서, 정말로 사용하지 않으시겠습니까? Observable은 오래된 코드이기 때문에 Observable이 "손으로"처리한다고 생각합니다. 게다가 나중에 코드에 "주변에"물건을 넣어야 할 수도 있습니다. – Merc

+1

예, 좋습니다.나는 코드가 걱정스러워 보일 때 미묘한 차이가있어 심지어 한 쌍의 눈조차도 놓칠 수 있다고 생각하고 있습니다. 그럼 Aspect.after()와 topic.publish에 중복 된 억제 필터는 어떻습니까? – bishop

관련 문제