2016-05-13 10 views
2

私の目標は、コンポーネントが親アイテムを識別できるときにアイテムリストにプッシュすることです。 問題は私がリストにpushingしているときです。console.log()はオブジェクトがそこにあることを示していますが、リストを返して別の関数でキャッチするとリストには何もありません。 アイテムリストは、上のコードが実行される前に返されると思います。angularJSとTypescriptの約束

private get_items_for_request() { 
    return this.Item.forRequest(this.request.id, ['group']) 
    .then((_items) => { 
     var items = []; 
     for (var item of _items) { 
     return this.ItemComponent.forItem(item.id, ['type']) 
      .then((_components) => { 
      for (var component of _components) { 
       if (component.type.can_identify_item) { 
       items.push({ 
        group_id: item.group.reference, 
        identifier_code: this.remove_check_digit_if_necessary(
         component.identifier_code), 
        quantity: 1 
       }); 
       break; 
       } 
      } 
      }, (reason) => { 
      this.Toast.error(
       this.gettextCatalog.getString('components.load_failed')); 
      return []; 
      }); 
     } 
     return items; 
    }, (reason) => { 
     this.Toast.error(
      this.gettextCatalog.getString('items.failed_load')); 
     return []; 
    }); 
} 

答えて

2

私は、コード自体ではなく、あなたのアプローチに問題があることを恐れています。約束はちょうどその約束です - 将来データの約束です。したがって、関数が返されると(すぐに)、約束はまだ解決されず、呼び出し元関数が取り込むデータはまだ空です。あなたのコードではconsole.log()は見えませんが、一度データが受信されると呼び出されます。これで、データがログに記録されます。問題はすでにget_items_for_request()が返され、呼び出し元関数がすでに移動していた時点です。

約束を使用する場合は、約束が解決されたらコールバックを使用する必要があります。しかし、実際のデータが呼び出し元に返されるようにするには、データを同期的にフェッチする必要があります。

同期フェッチの場合は、this responseをチェックします。ただし、同期フェッチはスクリプトの応答性を損なうことに注意してください。

(プロミスを使用して)非同期フェッチの場合、すべてのデータがフェッチされたらコールバックを定義する必要があります。あなたのコードを修正しようとはしませんが、javascriptの次のスケッチに沿って進んでください。それは単なるスケッチであることを念頭に置いていますが。

function get_items_for_request(onSuccess) { 
    var items = [] 
    var total = -1 
    var sofar = 0; 
    this.Item.forRequest(this.request.id, ['group']) 
    .then(function (_items) { 
     var items = []; 
     total = _items.length // remember how many nested calls will be made 
     for (var item of _items) { 
     this.ItemComponent.forItem(item.id, ['type']) 
      .then(function (_components) { 
      // push received data to the items array here 
      sofar++ 
      if (sofar == total) { // all done 
       onSuccess(items) 
      } 
      } 
     } 
    } 
} 
0

最初の約束コールバックでは、2つの戻り値があり、最初の値が返されます。最初のforの後に約束を返します。これはundefinedに解決されます。あなたは約束の配列を待つべきです、それぞれはthis.ItemComponent.forItemコールに対応しています。 https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/all

あなたはこのような何かをする必要があります:

Promise.all

はこれで助け

return this.Item.forRequest(this.request.id, ['group']).then((_items) => { 
     return Promise.all(_items.map(function (item) { 
      return this.ItemComponent.forItem(item.id, ['type']).then((_components) => { 
       for (var component of _components) { 
        if (component.type.can_identify_item) { 
         return { 
          group_id: item.group.reference, 
          identifier_code: this.remove_check_digit_if_necessary(
           component.identifier_code), 
          quantity: 1 
         }; 
        } 
       } 
      }, (reason) => { 
       this.Toast.error(
        this.gettextCatalog.getString('components.load_failed')); 
       return []; 
      }); 
     })); 
    }, (reason) => { 
     this.Toast.error(
      this.gettextCatalog.getString('items.failed_load')); 
     return []; 
    }) 

一つだけのアイテムをしたい場合は、結果の配列内の最初の非falsy要素を見つける

+0

@GiftZwergrapper動作コードを受信したい場合は、plunkrの例、または少なくともファイル全体をリンクする必要があります。私はあなたが何を期待しているのかわからない、我々は媒体ではない。 Angular 1を使用している場合、 '$ q'サービスはPromiseライブラリです。 –

+2

@GiftZwergrapperまた、私が指摘したエラーはまだそこにあることに注意してください、あなたはここで下降音符で少し積極的です。 –

+0

角度では、同じ目的で '$ q.all'を使うことができます – Icycool