Занавес javascript (используемый для обозначения занятого процесса) не отображается для всего процесса. Возможно, я недостаточно понимаю обратный вызов

У меня есть процесс, в котором пользователь помещает список с разделителями-запятыми, который затем обрабатывается по одному элементу за раз. Я хочу иметь возможность указать пользователю, что он обрабатывается, и сообщить им, когда это будет сделано. Поэтому я использовал идею занавеса из повтора Боргара для ... Div Over Page. Это сработало, но занавес исчезнет задолго до завершения процесса. Я считаю, что это связано с тем, что каждый вызов в цикле forEach внутри функции importIDs вызывается асинхронно, таким образом возвращая управление до его завершения. (Я знаю, что это идея, лежащая в основе асинхронного кода.) Итак, что мне нужно сделать, чтобы не закрывать занавес до тех пор, пока это не будет выполнено?

HTML, вызывающий функцию

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

функция импорта

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

};

который вызывает функцию занятости

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

который, в свою очередь, обрабатывает переданный цикл, который вызывает 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;
    });
};

который запускает каждый URL-адрес с помощью getDefer

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

};

Я думаю, что у меня есть весь соответствующий код выше. Я думал, что отправка цикла через занятый процесс будет удерживаться до завершения, а затем return, вместо этого, он удерживается, пока он не запускает каждую итерацию, а затем возвращается до того, как они будут завершены.

Как всегда, спасибо за любой вклад и критику.


person Mark    schedule 09.03.2010    source источник


Ответы (1)


Пара интересных ошибок в вышеупомянутом. В основном, если список идентификаторов в массиве слишком велик, он пропускает больше трафика в базу данных, чем он может обрабатывать. Поэтому я перешел к рекурсивной функции вместо цикла 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;
            });
        }
    }
};
person Mark    schedule 09.03.2010