dart - 服务器回调发生 4 次而不是 1 次

标签 dart dart-html dart-async

我注意到在执行服务器调用时发生了以下情况,这里出了什么问题!

 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”中的 items 字段为空,而最后一个显示正确执行的项目。

附上问题说明。

issue illustration

更新

收到答案后,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..');
  }
  } 
}

第二个屏幕截图显示更新后的输出 illustration 2

最佳答案

您收听一个流,预计会收到多个事件。

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

此属性返回四个值之一:

  • 未初始化 - 尚未开始加载
  • 正在加载 - 正在加载
  • 交互式 - 已加载足够的内容并且用户可以与其交互
  • 完成 - 满载

如果您对未初始化加载交互式不感兴趣,您可以检查

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

更新(第二期)

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');
  }
} 

关于dart - 服务器回调发生 4 次而不是 1 次,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26439092/

相关文章:

ajax - 尝试测试异步Dart Ajax HttpRequest时出错

asynchronous - 返回void与返回Future <void>有什么区别?

dart - 带有文本标签的 float 操作按钮。 flutter

authentication - Dart 登录/注销示例

dart - 类没有 setter '_scheduler' 的实例

css - 如何使用 Dart 设置 SVG 样式?

dart - 在完成功能调用之前,完成了Future

json - 我的Flutter移动应用程序可以使用我的Google Apps脚本吗?

dart - Flutter-单击照片后如何在屏幕上保持相机?

带后缀的 Flutter TextField