Javascript 如何让多个承诺操作同一个DOM元素作为副作用,并获得一致的结果?

Javascript 如何让多个承诺操作同一个DOM元素作为副作用,并获得一致的结果?,javascript,ajax,caching,dojo,Javascript,Ajax,Caching,Dojo,我有以下Dojo 1.9代码,可以异步加载2个表(某些名称已更改): 我遇到的问题本质上是一个竞赛条件: loadPanel1在本地启动并缓存旧状态 loadPanel1显示状态为的加载消息 loadPanel1开始加载面板 loadPanel2启动并缓存loadPanel1放置的加载消息 loadPanel2用相同的消息替换加载消息 加载面板2开始加载面板2 loadPanel1完成加载面板并将其缓存回旧状态 loadPanel2完成加载并用缓存的加载消息替换放回的旧状态loadPanel1

我有以下Dojo 1.9代码,可以异步加载2个表(某些名称已更改):

我遇到的问题本质上是一个竞赛条件:

  • loadPanel1在本地启动并缓存旧状态
  • loadPanel1显示状态为的加载消息
  • loadPanel1开始加载面板
  • loadPanel2启动并缓存loadPanel1放置的加载消息
  • loadPanel2用相同的消息替换加载消息
  • 加载面板2开始加载面板2
  • loadPanel1完成加载面板并将其缓存回旧状态
  • loadPanel2完成加载并用缓存的加载消息替换放回的旧状态loadPanel1 一个复杂的情况是,有时候,当页面加载时,globalError已经显示了一个状态,并且该状态不应该被任何loadPanel方法擦除。因此,无论loadPanel1()或loadPanel2()最后完成,都需要保留该状态。此外,Panel1本身有几个链接,可以更改Panel1的内容,从而添加一条状态消息并重新加载面板(之后消息仍应保留)。Panel2在加载后不会重新加载

    因此,有几个工作流:

  • 页面加载没有状态消息,两个面板都加载,无论哪个面板在何时完成,都不应显示状态消息
  • 页面加载状态消息,两个面板都加载,无论哪个面板在何时完成,原始状态消息都应保留
  • 页面和面板已加载。用户执行更改panel1内部状态的操作。该操作显示一条状态消息,panel1被重新加载,并且该操作显示的状态消息应在面板加载后保留
  • 加载面板时出错,在这种情况下,无论何时、哪个面板以及有多少面板未能加载,错误消息都应显示为状态消息

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

    解决方案是不使用要替换的单个状态消息。相反,将其设置为一个列表,每个组件都可以在其中附加、更改或删除自己的消息。你的逻辑应该是

    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
    管理该状态。加载功能应该完全相同,但是面板可能会决定只显示列表中最前面的消息,或者最近显示的消息。

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

    使用dojo/promise/all怎么样
    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);
        });
    }