2017-06-01 15 views
0

我已经是异步加载2个表下面的道场1.9的代码(一些名字更改):如何让多个承诺操作相同的DOM元素作为一致结果的副作用?

function loadPanel1() {            

    // set 'Loading Tool' status message              
    var actionStatus = dom.byId("globalError");            
    var oldStatus = actionStatus.innerHTML;             
    var oldStatusClass = actionStatus.className;            
    actionStatus.className = "globalInfo";             
    actionStatus.innerHTML = globalInfoMessage            
      + loadingMessage;             

    // Post the data to the server               
    request                     
      .post("loadPanel1.action", {          
       data : {                  
        "projectOid" : projectOid,            
        "oid" : projectStreamOid             
       }                    
      })                    
      .then(                   
        function(response) {              
         if (CommonUtils.checkForLoginPage(response)) {      
          return;               
         }                  

         dom.byId("Panel1").innerHTML = response;  

         // restore previous action status          
         var actionStatus = dom.byId("globalError");       
         actionStatus.innerHTML = oldStatus;         
         actionStatus.className = oldStatusClass;        
         connectLinks();              
        },                  
        function(error) {               
         if (error instanceof SyntaxError) {         
          location.reload(true);           
         } else if (error instanceof Error) {         
          var actionStatus = dom           
            .byId("globalError");          
          actionStatus.innerHTML = globalErrorMessage      
            + loadingErrorMessage;      
          actionStatus.className = "globalError";       
         }                  
        });                  
} 

//connectLinks connects event handlers to several links in Panel1 that reload the panel using loadPanel1() when successful. 

/**                       
* Posts the search form criteria to the server via ajax call.        
*/                       
function loadPanel2() {            

    // set 'Loading Tool' status message              
    var actionStatus = dom.byId("globalError");            
    var oldStatus = actionStatus.innerHTML;             
    var oldStatusClass = actionStatus.className;            
    actionStatus.className = "globalInfo";             
    actionStatus.innerHTML = globalInfoMessage            
      + loadingMessage;             

    // Post the data to the server               
    request                     
      .post("loadPanel2.action", {          
       data : {                  
        "projectOid" : projectOid,            
        "oid" : projectStreamOid             
       }                    
      })                    
      .then(                   
        function(response) {              
         if (CommonUtils.checkForLoginPage(response)) {      
          return;               
         }                  

         dom.byId("Panel2").innerHTML = response;  

         // restore previous action status          
         var actionStatus = dom.byId("globalError");       
         actionStatus.innerHTML = oldStatus;         
         actionStatus.className = oldStatusClass;        
        },                  
        function(error) {               
         if (error instanceof SyntaxError) {         
          location.reload(true);           
         } else if (error instanceof Error) {         
          var actionStatus = dom           
            .byId("globalError");          
          actionStatus.innerHTML = globalErrorMessage      
            + loadingErrorMessage;      
          actionStatus.className = "globalError";       
         }                  
        });                  
} 

我的问题本质上是一个竞争条件:

  1. loadPanel1启动并缓存旧状态本地;
  2. loadPanel1在状态中显示加载消息;
  3. loadPanel1开始加载面板;
  4. loadPanel2启动并缓存loadPanel1放置的加载消息;
  5. loadPanel2用相同的消息替换加载消息;
  6. loadPanel2开始加载Panel 2;
  7. loadPanel1完成加载面板并将其缓存的旧状态放回;
  8. loadPanel2完成加载并替换放置的旧状态loadPanel1和它缓存的加载消息!

一个复杂情况是,有时候,当页面加载时,globalError已经显示一个状态,并且该状态不应该被loadPanel方法擦除。因此无论loadPanel1()或loadPanel2()是否最后完成,都需要保留该状态。此外,Panel1本身具有多个链接,可以更改Panel1的内容,然后添加状态消息并重新加载面板(之后消息仍然应该保留)。 Panel2在加载后不会重新加载。

所以有几个流程:

  1. 页无负荷状态消息,无论是面板加载,无论是哪一个完成时,没有状态消息应显示;
  2. 页面加载WITH状态消息,这两个面板都会被加载,并且无论哪个面板何时完成,原始状态消息应该保留;
  3. 页面和面板被加载。用户执行更改panel1内部状态的操作。该动作显示状态消息,面板1重新加载,并且面板加载后应该保留动作显示的状态消息。
  4. 加载面板时出现错误,在这种情况下,应显示错误消息为状态消息,而不管何时加载哪个面板和多少面板。

我不禁想起有一个优雅的解决方案,使用外部方法缓存动作消息,但Google在这方面并没有真正帮助我。大多数关于使用加载消息进行多个异步加载的文章都涉及在加载最终内容的相同位置显示加载消息,这在这种情况下不起作用。

+0

使用dojo/promise/all https://dojotoolkit.org/reference-guide/1.10/dojo/promise/all.html – Radex

回答

0

在与我的同事讨论最佳方法后,我决定让异步加载的组件使用单独的消息显示,而不是尝试在同一显示中调整消息。

1

解决方案是不会有您要替换的单个状态消息。相反,将其作为列表,每个组件都可以附加,更改或删除自己的消息。你的逻辑应该是这样

load(x) { 
    const message = MessagePanel.newMessage(); 
    message.setContent(loader); 
    message.show(); 
    fetch(x).then(res => { 
     if (res.isMessage) 
      message.setContent(res); 
     else 
      message.hide(); 
    }, err => { 
     message.setContent(err); 
    }); 
} 

一些超时后,或在用户交互,你要再次隐藏消息,使得列表不会无限增长。

如果您确实希望/只能显示一条消息,请使MessagePanel管理该状态。 load函数应该完全相同,但面板可能决定仅显示列表中的顶部消息,或者显示最近显示的消息。

相关问题