Functions within a loop using requirejs

谁说我不能喝 提交于 2019-12-11 08:25:31

问题


I'm having an issue with calling functions within a loop across different modules using requirejs. The function call within the loop resides in module A and executes a function in module B that fires off an Ajax request using jQuery. Each iteration of the loop fires off a different request with different arguments being passed to module B's function that fires off the Ajax request. When the success function of the Ajax request executes, I find that all my argument values are always the values of the last Ajax call made, for all 4 separate Ajax calls.

I've done some googling and it sounds like this is a pretty common problem when executing a function within a loop. The fix tends to be to break out the function call into a different function, creating a different scope. Since my loop and Ajax calls are in 2 different modules I had assumed this would solve that issue, however it still persists.

I've tried some solutions in other stack overflow posts like: JSlint error 'Don't make functions within a loop.' leads to question about Javascript itself and How to pass parameter to an anonymous function defined in the setTimeout call? without success. Anyone have any idea?

Sample code for loop module A:

define(["mpos"],
    function(mpos){

        var monitor = {
            startMonitoring : function(poolObj){    
                // Start Monitoring
                $.each(mpos.msgs, function(action,callback){
                    poolObj.action = action;
                    mpos.sendApiRequest(poolObj,action,callback);

                });
            }
        };

        return monitor;
    }
);

Sample code for Ajax module B - this module is referenced as mpos in module A

define(["mule","constants"],
function(mule,constants){

    var mpos = {
        sendMessage : function(postData,callback,$poolOut){

            return $.ajax({
                'type':'post',
                'url':constants.URLS.proxy,
                'data':{'url':postData},
                success : function(data){
                    // if we have $poolOut we know this is a mpos call
                    if($poolOut != undefined){
                        var keys = Object.keys(data);
                        // add poolOut to data
                        data.poolOut = $poolOut;

                        var poolObj = $poolOut.data('poolObj');
                        if(poolObj){
                            var action = poolObj.action;
                            console.log(poolObj,action);
                            if(action){
                                if(action == "getuserstatus"){
                                    mule.registerPool(poolObj);
                                }
                            } else {
                                log.error("No action on poolObj while attempting to calculate the need for a registerPool call");
                            }
                        }
                    }
                    // parse data
                    callback.apply(this, data);
                },
                error : function(x,h,r){ ... },
                dataType : 'json'
            });
        },
        sendApiRequest : function(poolObj,action,callback){
            var url = poolObj.url + '&page=api&action=' + action;

            var $poolOut = constants.cache.monitorOutput.find('.pool-out.' + poolObj.id);

            var dfd = mpos.sendMessage(url,callback,$poolOut);

            $.when(dfd).always(function(){
                var refreshTimer = setTimeout(function(){
                    if(constants.state.monitorEnabled){
                        mpos.sendApiRequest(poolObj, action, callback);
                    }
                }, poolObj.refreshRate);

            });
        },
        msgs : {
            "getuserstatus" : function(data){ ... },
            "getpoolstatus" : function(data){ ... },
            "getuserworkers" : function(data){ ... },
            "getuserbalance" : function(data){ ... }
        }
    };

    return mpos;
}
);

Thanks!


回答1:


NOTE: I am assuming that $poolOut.data('poolObj') is being used to find the poolObj instance passed in the call to startMonitoring, and will return the same instance each time.

You state, "Each iteration of the loop fires off a different request with different arguments being passed to module B's function that fires off the Ajax request."

This statement is not correct. Each iteration fires off a different request with the first argument poolObj being the same in each iteration.

In your .each iteration, you are overwriting the value of poolObj.action before each call to sendApiRequest.

In the AJAX success handler, which is likely invoked after all iterations have completed, the value of poolObj.action will have the value you set it to in the last iteration.

To solve this, I think you need to pass action as a parameter to sendMessage, too, so that a separate value is being stored in the closure for each function call.

var mpos = {
    sendMessage : function(postData,action,callback,$poolOut){

        return $.ajax({
            'type':'post',
            'url':constants.URLS.proxy,
            'data':{'url':postData},
            success : function(data){
                // if we have $poolOut we know this is a mpos call
                if($poolOut != undefined){
                    var keys = Object.keys(data);
                    // add poolOut to data
                    data.poolOut = $poolOut;

                    var poolObj = $poolOut.data('poolObj');
                    if(poolObj){
                        // action is not guaranteed to be the same as poolObj.action here,
                        // since poolObj.action may have changed since this function was first called
                        console.log(poolObj,action);
                        if(action){
                            if(action == "getuserstatus"){
                                mule.registerPool(poolObj);
                            }
                        } else {
                            log.error("No action on poolObj while attempting to calculate the need for a registerPool call");
                        }
                    }
                }
                // parse data
                callback.apply(this, data);
            },
            error : function(x,h,r){ ... },
            dataType : 'json'
        });
    },
    sendApiRequest : function(poolObj,action,callback){
        var url = poolObj.url + '&page=api&action=' + action;

        var $poolOut = constants.cache.monitorOutput.find('.pool-out.' + poolObj.id);

        var dfd = mpos.sendMessage(url,action,callback,$poolOut);

        $.when(dfd).always(function(){
            var refreshTimer = setTimeout(function(){
                if(constants.state.monitorEnabled){
                    mpos.sendApiRequest(poolObj, action, callback);
                }
            }, poolObj.refreshRate);

        });
    },
    msgs : {
        "getuserstatus" : function(data){ ... },
        "getpoolstatus" : function(data){ ... },
        "getuserworkers" : function(data){ ... },
        "getuserbalance" : function(data){ ... }
    }
};


来源:https://stackoverflow.com/questions/22120713/functions-within-a-loop-using-requirejs

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!