2016-08-26 6 views
0

私はpropertyTemplate配列を再作成/ロードするための再帰関数の設定をしています。再帰プロミス - 時にはうまくいきません

最初の関数は、このようなオブジェクトを指定している:私はきちんと私のUIを移入するようにオブジェクトの配列には、このオブジェクトを再作成する必要があり

{ 
    staffedLocation: ['schedulingGroup',{property: 'staff',subProperties: ['description']}], 
    staff: true, 
    assignedShifts: true, 
    editedShifts: true, 
    deletedShifts: true, 
    unassignedShifts: true, 
    rangeStart: true, 
    rangeEnd: true 
} 

を:

[ 
    {checked: null, name: "staffedLocation", properties: [ 
     {checked: null, name: "oid", properties: null, toggle: null, type: "integer"}, 
     {checked: null, name: "_class", properties: null, toggle: null, type: "string"}, 
     {checked: true, name: "schedulingGroups", properties: null, toggle: null, type: "list"}, 
     {checked: null, name: "staff", properties: [ 
      {checked: null, name: "oid", properties: null, toggle: null, type: "integer"}, 
      {checked: null, name: "_class", properties: null, toggle: null, type: "string"}, 
      {checked: true, name: "description", properties: null, toggle: null, type: "string"}, 
      {checked: null, name: "limits", properties: null, toggle: null, type: "list"}, 
      {checked: null, name: "weeklyMaxHours", properties: null, toggle: null, type: "integer"} 

     ], toggle: true, type: "list"}, 
    ], toggle: true, type: "staffedLocation"}, 
    {checked: null, 
    name: "staff", properties: [ 
     {checked: null, name: "oid", properties: null, toggle: null, type: "integer"}, 
     {checked: null, name: "_class", properties: null, toggle: null, type: "string"}, 
     {checked: null, name: "description", properties: null, toggle: null, type: "string"}, 
     {checked: null, name: "limits", properties: null, toggle: null, type: "list"}, 
     {checked: null, name: "weeklyMaxHours", properties: null, toggle: null, type: "integer"} 
    ], toggle: true, type: "staff"}, 
    {checked: null, name: "assignedShifts", properties: null, toggle: null, type: "shiftForEmail"}, 
    {checked: null, name: "editedShifts", properties: null, toggle: null, type: "shiftForEmail"}, 
    {checked: null, name: "deletedShifts", properties: null, toggle: null, type: "shiftForEmail"}, 
    {checked: null, name: "unassignedShifts", properties: null, toggle: null, type: "shiftForEmail"}, 
    {checked: null, name: "rangeStart", properties: null, toggle: null, type: "timestamp"}, 
    {checked: null, name: "rangeEnd", properties: null, toggle: null, type: "timestamp"} 
] 

現在、私convert関数を呼び出すと、そのオブジェクトは歩き回り、オブジェクトの配列を作成し始めます。ただし、convertRecurseにヒットすると、アイテムの1つのプロパティを収集する約束が作成されます。

最初は、すべてのプロパティを集めた後、約束事の中にあるすべての機能を適切に入れ子にすると思っていました。しかし、最初にページに移動してテンプレートを読み込むと、プロパティは表示されません。テンプレートをもう一度開いて再起動しても動作します。

私は約束を連鎖して、第2約束が進むのを待つと考えています。しかし、私は彼らがどのように働くかをよく理解していません。

function convert(template){ 
    $scope.propertyTemplate = []; 
    for(var k in template){ 
     var obj = {}; 
     obj.checked = null; 
     obj.name = k; 

     if(template[k] !== true){ 
      convertRecurse(template[k], obj, k); 
     } else { 
      obj.properties = null; 
      obj.toggle = null; 
     } 

     $scope.propertyTemplate.push(obj); 
    } 
} 

function convertRecurse(array, obj, parent){ 

    var propArr = []; 

    var namespace = new namespaceFactory(parent); 
    namespace.init(); 

    namespace.fetchProperties().then(function(props){ 
     props.forEach(function(prop){ 

      var fetchObj = {}; 
      fetchObj.name = prop.property; 
      fetchObj.type = prop.type; 
      fetchObj.checked = null; 
      fetchObj.properties = null; 
      fetchObj.toggle = null; 

      propArr.push(fetchObj); 
     }); 

     return propArr; 

    }).then(function(){ 

     var objArr = []; 

     for(var j = 0; j < array.length; j++){ 

      if(typeof array[j] === 'object'){ 
       objArr.push(array[j]); 
       array.splice(j, 1); 
       j--; 
      } 

      for(var i = 0;i < propArr.length; i++){ 

       if(array[j] === propArr[i].name){ 
        propArr[i].checked = true; 
       } 
      } 
     } 

     for(var k = 0; k < objArr.length; k++){ 
      var propObj = {}; 
      propObj.checked = null; 
      propObj.name = objArr[k].property; 

      if(objArr[k].subProperties){ 
       convertRecurse(objArr[k].subProperties, propObj, objArr[k].property) 
       for(var x = 0; x < propArr.length; x++){ 
        if(propArr[x].name === propObj.name){ 
         propArr.push(propObj); 
         propArr.splice(x, 1); 

        } 
       } 
      } else { 
       propObj.properties = null; 
       propObj.toggle = null; 
      } 
     } 

     obj.properties = propArr; 
     obj.toggle = true; 

    }).catch(console.log.bind(console)); 
} 

私の問題は、初めてこの関数を呼び出すときに読み込まれないことです。

enter image description here

私は再びそれを呼び出す場合は、すべてが完璧に動作するようです。

enter image description here

+0

'obj.properties = propArr;'どこが 'obj'ですか? – Katana314

+0

objがparamsの一部として渡されます –

+0

convertRecurseの外で、 'obj.properties'がいつ設定されるかをどのように知っていますか? (約束がまだ完了していないので、関数が終了した瞬間は設定されません)。 – Katana314

答えて

1

あなたが懸念非同期の流れを持っている問題。現在書かれているコードはconvertRecurse()を同期として扱いますが、実際は非同期です。

コードは難しいが、難しいのはシンクロナストランスフォームなので、わからない。

修正プログラムは、ループ内で非同期操作が発生するため、かなり広範囲です。具体的には、次のいずれかが必要です。

  • あなたとわかるように、平行して集計約束

で非同期操作を実行する.then()チェーン、または

  • を構築することにより、順次非同期操作を実行します以下を参照してください。非同期フローの主要な側面は、適切なリターンをすべて通過させることです。

    ここでは、シーケンシャルなアプローチを採用し、次のとおりです。

    function convert(template) { 
        $scope.propertyTemplate = []; 
    
        // Make array of template's enumerable keys 
        // See https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Object/keys 
        var keys = Object.keys(template); 
    
        // Build a .then() chain from `keys`. 
        return keys.reduce(function(promise, k) { 
         return promise.then(function() { 
          var obj = { 
           name: k, 
           checked: null, 
           properties: null, 
           toggle: null 
          }; 
          if(template[k] !== true) { 
           return convertRecurse(template[k], obj, k); 
          } else { 
           return obj; 
          } 
         }).then(function(obj_) { 
          $scope.propertyTemplate.push(obj_); 
          return obj_; // make obj_ available to the caller 
         }); 
        }, $q.resolve()); // $q is assumed 
    } 
    
    function convertRecurse(array, obj, parent) { 
        var namespace = ... 
        return namespace.fetchProperties().then(function(props) { 
         var propArr = ... // some synchronous transform of (props) 
         var objArr = ... // some synchronous transform of (array, propArr) 
    
         // Build a .then() chain from `objArr` 
         return objArr.reduce(function(promise, o) { 
          return promise.then(function() { 
           if(o.subProperties) { 
            var propObj = { 
             name: o.property, 
             checked: null, 
             properties: null, 
             toggle: null 
            }; 
            return convertRecurse(o.subProperties, propObj, o.property).then(function() { 
             propArr = ... // some synchronous transform of (propArr, propObj) 
            }); 
           } 
          }); 
         }, $q.resolve()) 
         .then(function() { 
          obj.properties = propArr; 
          obj.toggle = true; 
          return obj; // deliver the augmented obj back to the caller. 
         }); 
        }).catch(function(error) { 
         console.log(error); 
         throw error; 
        }); 
    } 
    

    私の一部にミスがなければ(すべてではないことは不可能)、すべてを行う必要がために省略されている3つの変換のためのコードを再挿入であります全体的な流れの明瞭さ。個人的には、変換を関数として記述し、そのコードをそのまま継承します。

  • +0

    ありがとう!すべてが今すぐうまくいくように見えます! –

    関連する問題