Currently I'm trying to make repeating Ajax-Calls dynamic so my code gets better manageable. While doing so I encountered that I sometimes need dynamic data-attributes and -values. There is always just one data-value that changes, the other parameters stay the same. Doing so I could easily chain promises.
So here is an example of what I use as template for those Ajax-Calls:
var prepareAjax = {
iterateValues: [1230,1280,4000,9000],
ajaxOptions: [{
timeout: 10000,
type: "GET",
data: `{
param1: item,
param2: obj.sessionId,
param3: 1
}`,
url: 'https://someurl.tld/target'
}],
sessionId: '<somestring>'
};
After this object I'm calling a function that should extract the ajaxOptions
from the object like so:
function fetchChain(obj)=>{
var ajaxPromises = [], tempObj;
obj.iterateValues.map((item, index)=> {
tempObj = obj.ajaxOptions[0];
tempObj.data = eval('('+tempObj.data+')');
ajaxPromises.push(new Promise(
(resolve, reject)=>{
namespace.fetchData(tempObj);
}
);
}
}
What I'm doing here is creating a promise and Ajax-Call for every ìterateValue
. Then I'm using eval (yes, evil) to resolve the variables of the current context (fetchChain
) and feed it to fetchData
. The functions are executed withhin a namespace, so I'm calling them with namespace.fetchChain(prepareAjax)
in example.
The problem
This example only works for one iteration since eval also seems to change obj
permanently, even if I only eval/modify the tempObj
, but obviously I want to reuse the template on every iteration. The only value that needs to be resolved is item
, the parameters stay the same.
I also know new Function()
is a better alternative to eval
but I couldn't get it to work neither. What is more weird for me is that the function worked previously when eval'ing the data-attributes directly inside the Ajax-Call without using a preparation function like for fetchChain()
. I'm stuck at this point, even after reading through several Answers on SO.
For completeness, here is the fetchData function:
function fetchData(obj)=>{
// single ajax-calls should use a delay of 0
obj.timeout = ((obj.timeout) ? obj.timeout : 10000),
obj.retries = ((obj.retries) ? obj.retries : 5),
obj.delay = ((obj.delay) ? obj.delay : 1000),
obj.type = ((obj.type) ? obj.type : "GET"),
obj.cnt = ((obj.cnt) ? obj.cnt++ : 0);
var sumDelay = obj.delay*(obj.cnt+1);
setTimeout(()=>{
return new Promise((resolve, reject)=>{
return $.ajax(obj)
.done((response)=>{
return resolve(response);
}).fail((error)=>{
if(obj.cnt++ >= obj.retries){
return resolve('Error');
}
fun.fetchData(obj);
}).always((xd)=>{
})
})
}, sumDelay)
}
A Solution
A solution I'm thinking of would be to prepare the object before feeding it to fetchChain()
. Or to be more clear: in the context where prepareAjax
gets created. Obviously I would prefer to directly handle this process inside fetchChain()
.
The Error
When executing fetchChain
like described above I'm getting the Error Unexpected Identifier
on second iteration inside of the eval. ([object Object]) When debugging one could see the obj
also changed its value for data
.