javascript 窗帘(用于指示繁忙的进程)未显示整个进程。可能我对回调的理解不够

发布于 2024-08-24 06:17:29 字数 2275 浏览 4 评论 0原文

我有一个流程,用户放入一个逗号分隔的列表,然后一次处理一个项目。我希望能够向用户表明它正在处理,并让他们知道它何时完成。所以我使用了 Borgar 重播中的窗帘创意 ...在页面上划分。 这很有效,但在该过程完成之前窗帘就消失了。我相信这是因为 importIDs 函数内 forEach 循环中的每个调用都是异步调用的,从而在完成之前返回控制权。 (我知道这就是异步代码背后的想法。)那么我需要做什么才能保持帷幕直到完成?

调用函数

<label>Import list:</label><input style="width: 30em;" type="text" id="jcDelimitedList"/><input onclick="importIDs('jcDelimitedList','selectedJobCodes','AddJobCode');" type="button" value="Do It"/>

import 函数

    importIDs = function(dList,nodeId,actionName){
    busyProcess(function(){
        var ids = dojo.byId(dList).value;
        dojo.forEach(ids.split(","),function(entry,i){doAssosiate(nodeId,actionName,null,dojo.byId(entry));});
    });

};

的 HTML ,该函数调用 busy 函数,

    busyProcess = function(callback){
    var ret;
    var curtain = document.body.appendChild(document.createElement('div'));
    curtain.id = "curtain";
    curtain.onkeypress = curtain.onclick = function(){return false;};
    try{
        ret = callback();
    }finally{
        curtain.parentNode.removeChild(curtain);
    }
    return ret;
};

而 busy 函数又处理传入的循环,该循环为数组中的每个元素调用 doAssosiate:

    doAssosiate = function(nodeID,actionName,evt,aNode){
    if(aNode==null)return;
    var node = dojo.byId(nodeID);
    var newNode;
    var target = evt!=null?evt.target:aNode;
    newNode = dojo.clone(target);
    var tID = target.id;
    var sUrl = "action/groups." + actionName + "?id=" + tID  + "&groupID=" + groupID + bustCache("&");
    var get = getDefered(sUrl);
    get.addCallback(function(data){
        node.appendChild(newNode);
        target.parentNode.removeChild(target);  
        return data;
    });
    get.addCallback(function(data){
        dojo.behavior.apply();
        return data;
    });
};

它使用 getDefered 运行每个 url

getDefered = function(url){
console.log(url);
return dojo.xhrGet({
    url:url
});

};

我想我有上面所有相关的代码。我认为使用通过繁忙的进程发送循环将保持直到完成然后返回,而不是它保持直到它触发每个迭代,然后在完成之前返回。

一如既往地感谢您的任何意见和批评。

I have a process where a user puts in a comma delimited list that is then processed one item at a time. I want to be able to indicate to the user that it is processing and let them know when it is done. So I used the curtain idea from Borgar's replay to ... Div Over Page.
This worked but the curtain disappears well before the process is done. I believe it is because each call in the forEach loop inside the importIDs function is called asynchronously thus returning control back before it completes. (I know that is the idea behind asynchronous code.) So what do I need to do to keep the curtain up until it is done?

HTML that calls the function

<label>Import list:</label><input style="width: 30em;" type="text" id="jcDelimitedList"/><input onclick="importIDs('jcDelimitedList','selectedJobCodes','AddJobCode');" type="button" value="Do It"/>

import function

    importIDs = function(dList,nodeId,actionName){
    busyProcess(function(){
        var ids = dojo.byId(dList).value;
        dojo.forEach(ids.split(","),function(entry,i){doAssosiate(nodeId,actionName,null,dojo.byId(entry));});
    });

};

which calls the busy function

    busyProcess = function(callback){
    var ret;
    var curtain = document.body.appendChild(document.createElement('div'));
    curtain.id = "curtain";
    curtain.onkeypress = curtain.onclick = function(){return false;};
    try{
        ret = callback();
    }finally{
        curtain.parentNode.removeChild(curtain);
    }
    return ret;
};

which in turn processes the passed in loop that calls doAssosiate for each element in the array:

    doAssosiate = function(nodeID,actionName,evt,aNode){
    if(aNode==null)return;
    var node = dojo.byId(nodeID);
    var newNode;
    var target = evt!=null?evt.target:aNode;
    newNode = dojo.clone(target);
    var tID = target.id;
    var sUrl = "action/groups." + actionName + "?id=" + tID  + "&groupID=" + groupID + bustCache("&");
    var get = getDefered(sUrl);
    get.addCallback(function(data){
        node.appendChild(newNode);
        target.parentNode.removeChild(target);  
        return data;
    });
    get.addCallback(function(data){
        dojo.behavior.apply();
        return data;
    });
};

which runs each url with getDefered

getDefered = function(url){
console.log(url);
return dojo.xhrGet({
    url:url
});

};

I think I have all the relevant code above. I thought using sending the loop through the busy process would hold until finished and then return instead it holds until it fires off each iteration and then returns before they are complete.

As always thanks for any input and criticism.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

反差帅 2024-08-31 06:17:29

上面有几个有趣的错误。主要是如果数组中的 id 列表太大,它会在数据库中处理更多的流量,然后它就可以处理。所以我使用了递归函数而不是 foreach 循环。然后从 busyProcess 函数中删除了关闭窗帘的责任,并将其添加到在递归退出时关闭窗帘的递归调用中。对于任何关心的人,下面是更改后的功能。同时更改为使用 dojox.widget.Standby 作为窗帘。

    busyProcess = function(callback){
    var ret;
    document.body.appendChild(standby.domNode);
    standby.show();
    ret = callback();

    return ret;
};

现在不再调用 doAssosiate,而是调用 assosiateAll;

    importIDs = function(dList,nodeId,actionName){
    busyProcess(function(){
        var ids = dojo.byId(dList).value;
        var sourceNode = dojo.byId(nodeId);
        assosiateAll(ids.split(","),0,sourceNode,actionName);
    });
};




    assosiateAll = function(idArray,idx,sourceNode,actionName){
    if(idx <= idArray.length ){
        var target = dojo.byId(idArray[idx]);
        if(target == null){
            idx++;
            assosiateAll(idArray,idx,sourceNode,actionName);
        }else{
            var newNode = dojo.clone(target);
            var tID = target.id;
            var sUrl = "action/groups." + actionName + "?id=" + tID + "&groupID=" + groupID + bustCache("&");

            var get = getDefered(sUrl);
            get.addCallback(function(data){
                sourceNode.appendChild(newNode);
                target.parentNode.removeChild(target);
                return data;                    
            });
            get.addCallback(function(data){
                idx++;
                assosiateAll(idArray,idx,sourceNode,actionName);
                return data;
            });
            get.addCallback(function(data){
                dojo.behavior.apply();
                if (idx == (idArray.length -1)) {
                    standby.hide();
                }
                return data;
            });
        }
    }
};

A couple of interesting bugs in the above. Mainly if the list of ids in the array is to large it troughs more traffic at the database then it can handle. So I went to a recursive function instead of the foreach loop. Then removed the responsibility of turning off the curtain from busyProcess function and added it to the recursive call that turned the curtain off on exit of the recursion. For anyone that cares below are the changed functions. Also change to use dojox.widget.Standby for the curtain.

    busyProcess = function(callback){
    var ret;
    document.body.appendChild(standby.domNode);
    standby.show();
    ret = callback();

    return ret;
};

instead of calling doAssosiate now it calls assosiateAll;

    importIDs = function(dList,nodeId,actionName){
    busyProcess(function(){
        var ids = dojo.byId(dList).value;
        var sourceNode = dojo.byId(nodeId);
        assosiateAll(ids.split(","),0,sourceNode,actionName);
    });
};




    assosiateAll = function(idArray,idx,sourceNode,actionName){
    if(idx <= idArray.length ){
        var target = dojo.byId(idArray[idx]);
        if(target == null){
            idx++;
            assosiateAll(idArray,idx,sourceNode,actionName);
        }else{
            var newNode = dojo.clone(target);
            var tID = target.id;
            var sUrl = "action/groups." + actionName + "?id=" + tID + "&groupID=" + groupID + bustCache("&");

            var get = getDefered(sUrl);
            get.addCallback(function(data){
                sourceNode.appendChild(newNode);
                target.parentNode.removeChild(target);
                return data;                    
            });
            get.addCallback(function(data){
                idx++;
                assosiateAll(idArray,idx,sourceNode,actionName);
                return data;
            });
            get.addCallback(function(data){
                dojo.behavior.apply();
                if (idx == (idArray.length -1)) {
                    standby.hide();
                }
                return data;
            });
        }
    }
};
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文