2

サーバーの呼び出しを実行すると、以下が発生することに気付きました。ここで間違っていることは何ですか?

 getItems(){
    print('getItems');
    request = new HttpRequest();
    request.onReadyStateChange.listen(onData_getItems);

    request.open('POST', host+'/getItems');
    request.send(' ');  
}

onData_getItems(_){
   print('call');  // --> printed 4 times!!

if (request.readyState == HttpRequest.DONE && request.status == 200) { 
    print('Data loaded successfully..';
    
    print(request.responseText);   // --> printed 1 time!!
    for(Map item in JSON.decode(request.responseText)){
         LineItem..children.add(new OptionElement(value: item['Code'], data: item['Name']));
    }         
} 
else if (request.readyState == HttpRequest.DONE &&
  request.status == 0) { 
     print("could not connect to server, contact your admin");  
}
else print('something else');    // --> printed 3 times

}

上記は私のカスタム要素で実行されます:

class getPurchaseLines extends HtmlElement {
    static final tag = 'get-POlines';
    factory getPurchaseLines() => new Element.tag(tag);

    var shadow, LineItem, LineQty, Lineprice, clsBtn;

    getPurchaseLines.created() : super.created() {    
          shadow = this.createShadowRoot();      

         LineItem = new SelectElement()
               ..children.add(new OptionElement(value: '0', data:'Stock Code'));

          LineQty = new InputElement()..type='number'..placeholder='Qty'..style.width='50px';   
          Lineprice = new InputElement()..type='number'..placeholder='price'..style.width='50px';

          LineQty.onKeyUp.listen((e){if(LineQty.checkValidity() == false)LineQty.value='0';});
          Lineprice.onKeyUp.listen((e){if(Lineprice.checkValidity() == false)Lineprice.value='0';});

   shadow.host
            ..style.position='relative'
            ..style.display='inline-block'
            ..style.verticalAlign = 'top'
            ..style.backgroundColor = '#ffffff'
            ..style.boxShadow = '1px 1px 5px #333333'
            ..style.boxSizing = 'border-box'
            ..style.marginTop='2px'
            ..style.padding = '4px'
            ..style.paddingRight='30px'
            ..style.borderRadius='2px'
            ..style.fontSize='14px'  
            ..style.transition = 'all 0.2s ease-in'; 
   clsBtn
       ..onClick.listen((e)=> this.remove())
       ..style.position='absolute'
       ..style.right = '5px'
       ..style.top = '5px'
       ..style.color = 'black'
       ..style.cursor = 'pointer'
       ..style.zIndex = '1'
       ..style.fontSize = '16px'
       ..style.fontWeight = 'solid'  
       ..classes.add('ion-close-circled')
       ..text='x'
       ;

    shadow.nodes..add(LineItem)..add(LineQty)..add(Lineprice)..add(clsBtn);
   }

以下のように私の関数で呼び出されます:

   Future fonixFuture() => new Future.value(true);                 
       for (var line in orderLines){               
               fonixFuture()
                     .then((_)=> LineDisplay = new getPurchaseLines())
                     .then((_)=> LineDisplay.getItems())
                     .then((_)=> this.parent.nodes.add(LineDisplay))
                     .then((_)=>print(this.parent.nodes));
            }

最後の要素 (LineDisplay) のみが正しい getItem() の結果を示しています。たとえば、4 行ある場合、LineDisplay は次のようになります。

  1. カウンセリングで「call」を16回印刷しました
  2. 要素 LineDisplay をブラウザに 4 回表示する
  3. 最初の 3 つの 'LineDisplay' の項目フィールドは null ですが、最後の項目は正しく実行された項目を示しています。

問題の添付図。

問題の図

アップデート

回答を受け取った後、4 つの応答の問題は修正されましたが、最後の要素でのみ出力が受信されました! 更新されたコードは次のとおりです。

    return Future.forEach(orderLines, (ol) {
         return fonixFuture()
             .then((_)=>print(ol))
             .then((_)=> LineDisplay = new getPurchaseLines())
             .then((_)=> LineDisplay..getItems())
             .then((_)=> this.parent.nodes.add(LineDisplay))
             .then((_)=>print(this.parent.nodes));      
         });

カスタム要素は次のとおりです。

part of fonix_client_library;

class getPurchaseLines extends HtmlElement {
  static final tag = 'get-POlines';
  factory getPurchaseLines() => new Element.tag(tag);

  var shadow, LineItem, LineQty, Lineprice;

  getPurchaseLines.created() : super.created() {    
      shadow = this.createShadowRoot();      
      LineItem = new SelectElement()
        ..children.add(new OptionElement(value: '0', data:'Stock Code'));

      LineQty = new InputElement()..type='number'..placeholder='Qty'..style.width='50px';   
      Lineprice = new InputElement()..type='number'..placeholder='price'..style.width='50px';

      LineQty.onKeyUp.listen((e){if(LineQty.checkValidity() == false)LineQty.value='0';});
      Lineprice.onKeyUp.listen((e){if(Lineprice.checkValidity() == false)Lineprice.value='0';});

      shadow.host
            ..style.position='relative'
            ..style.display='inline-block'
            ..style.verticalAlign = 'top'
            ..style.backgroundColor = '#ffffff'
            ..style.boxShadow = '1px 1px 5px #333333'
            ..style.boxSizing = 'border-box'
            ..style.marginTop='2px'
            ..style.padding = '4px'
            ..style.paddingRight='30px'
            ..style.borderRadius='2px'
            ..style.fontSize='14px'  
            ..style.transition = 'all 0.2s ease-in'; 
   shadow.nodes..add(LineItem)..add(LineQty)..add(Lineprice);  
  }

 getItems(){
   print('getItems');
   request = new HttpRequest();
   request.onReadyStateChange.listen(onData_getItems);

   request.open('POST', host+'/getItems');
   request.send(' '); 
 }

 onData_getItems(_){
    if (request.readyState != HttpRequest.DONE) return;
    else
      print('responce recieved..: ${request.responseText}');

    if (request.readyState == HttpRequest.DONE && request.status == 200) { 
      fonixFooter.innerHtml='Items retreived..';
    
      print('responce after checking ifItemsretrieved..: ${request.responseText}');
    
          for(Map item in JSON.decode(request.responseText)){
                 LineItem..children.add(new OptionElement(value: item['Code'], data: item['Name']));
                 
          }

} 
   else if (request.readyState == HttpRequest.DONE &&
  request.status == 0) { 
    print('no server..');
  }
  } 
}

2 番目のスクリーンショットは、更新された出力を示しています イラスト2

4

1 に答える 1

2

ストリームをリッスンすると、複数のイベントを取得することが期待されます。

http://www.w3schools.com/jsref/prop_doc_readystate.asp言う

このプロパティは、次の 4 つの値のいずれかを返します。

  • uninitialized - まだ読み込みを開始していません
  • 読み込み中 - 読み込み中
  • interactive - 十分にロードされており、ユーザーはそれを操作できます
  • 完全 - 完全に読み込まれました

に興味がない場合はuninitialized、チェックしてください。loadinginteractive

onData_getItems(_){
  if (request.readyState != HttpRequest.DONE) return;
  print('call');  // --> printed 1 time

更新(第2号)

で非同期関数を実行すると、forEachおそらく期待どおりに動作しません

それ以外の

for (var line in orderLines){ 

使用する

return Future.forEach(orderlines, (ol) {
    return fonixFuture()
    .then((_)=> LineDisplay = new getPurchaseLines())
    .then((_)=> LineDisplay.getItems())
    .then((_)=> this.parent.nodes.add(LineDisplay))
    .then((_)=>print(this.parent.nodes));      
});

明確な理由なしに人為的に非同期実行を導入するのは少し奇妙に見えます

Future fonixFuture() => new Future.value(true);

したがって、上記のコード スニペットをアプリ コードに統合する方法を説明するのは難しいです。
問題が解決しない場合は、新しい質問を作成することをお勧めします。

アップデート

return Future.forEach(orderLines, (ol) {
  print(ol);
  LineDisplay = new getPurchaseLines();
  return LineDisplay.getItems()
  .then((success) {
    if(success) {
      parent.nodes.add(LineDisplay);
      print(this.parent.nodes);      
    } else {
      print('getItems() failed!');
    } // <== added
  });
});


Future getItems(){
  print('getItems');
  request = new HttpRequest();
  Completer completer = new Completer();
  request.onReadyStateChange.listen((_) => onData_getItems(completer)); // <== changed

  request.open('POST', host+'/getItems');
  request.send(' '); 
  return completer.future;
}

onData_getItems(Completer completer) {
  if (request.readyState != HttpRequest.DONE) {
    return;
  } else {
    print('responce recieved..: ${request.responseText}');
  }

  if (request.status == 200) { 
    fonixFooter.innerHtml='Items retreived..';

    print('responce after checking ifItemsretrieved..: ${request.responseText}');
    for(Map item in JSON.decode(request.responseText)){
      LineItem..children.add(new OptionElement(value: item['Code'], data: item['Name']));
    }
    completer.complete(true);
  } else if (request.readyState == HttpRequest.DONE && request.status == 0) { 
    print('no server..');
    completer.complete(false);
    // or completer.completeError('failed');
  }
} 
于 2014-10-18T11:27:38.380 に答える