dojo 我怎样才能让多个promise操作同一个DOM元素作为副作用而得到一致的结果呢?

uinbv5nw  于 2022-12-16  发布在  Dojo
关注(0)|答案(2)|浏览(154)

我有以下异步加载2个表的Dojo 1.9代码(更改了一些名称):

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. loadPanel 1启动并在本地缓存旧状态;
  2. loadPanel 1显示状态为加载消息;
  3. loadPanel 1开始加载面板;
  4. loadPanel 2启动并缓存loadPanel 1放置的加载消息;
  5. loadPanel 2用相同的消息替换加载消息;
  6. loadPanel 2开始加载面板2;
  7. loadPanel 1完成面板的加载,并将缓存的旧状态放回原处;
  8. loadPanel 2完成加载,并将loadPanel 1放回的旧状态替换为它缓存的加载消息!
    一个复杂的问题是,有时候,当页面加载时,globalError已经显示了一个状态,并且该状态不应该被任何一个loadPanel方法擦除。()或加载面板2()最后完成,则需要保留该状态。另外,Panel 1本身有多个链接,可以更改Panel 1的内容,然后添加一条状态消息并重新加载面板(在此之后消息应该仍然保留)。Panel 2在加载后不会重新加载。
    所以有几个工作流程:
    1.页面加载时没有状态消息,两个面板都加载,并且无论哪个面板何时完成,都不应显示状态消息;
    1.页面加载WITH状态消息,两个面板都加载,且无论哪一个在何时完成,原始状态消息都应保留;
    1.页面和面板已加载。用户执行更改panel 1内部状态的操作。该操作显示状态消息,panel 1已重新加载,并且该操作显示的状态消息在面板加载后应保持不变。
    1.加载面板时出错,在这种情况下,错误消息应显示为状态消息,而不管何时、哪个面板以及多少面板加载失败。
    我不禁想到,有一个优雅的解决方案,使用外部方法来缓存操作消息,但Google并没有真正帮助我。大多数关于使用加载消息进行多个异步加载的文章都涉及在最终内容加载到的同一位置显示加载消息,这在这种情况下没有帮助。
gudnpqoy

gudnpqoy1#

解决方案不是要替换一条状态消息,而是将它做成一个列表,每个组件都可以在其中添加、更改或删除自己的消息。

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函数应该做同样的事情,但是面板可能会决定只显示列表中最上面的消息,或者最近显示的消息。

ffscu2ro

ffscu2ro2#

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

相关问题