目前,我正在尝试使重复的 Ajax 调用动态化,以便我的代码变得更易于管理。在这样做时,我遇到有时需要动态数据属性和值。始终只有一个数据值发生变化,其他参数保持不变。这样做我可以轻松地实现链式 promise 。
下面是我用作 Ajax 调用模板的示例:
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>'
};
在这个对象之后,我调用一个函数,该函数应该从对象中提取ajaxOptions
,如下所示:
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);
}
);
}
}
我在这里所做的是为每个 ìterateValue
创建一个 promise 和 Ajax 调用。然后我使用 eval(是的,邪恶)来解析当前上下文 (fetchChain
) 的变量并将其提供给 fetchData
。这些函数是在命名空间内执行的,因此我在示例中使用 namespace.fetchChain(prepareAjax)
来调用它们。
问题
此示例仅适用于一次迭代,因为即使我只评估/修改 tempObj
,eval 似乎也会永久更改 obj
,但显然我想重用每次迭代的模板。唯一需要解析的值是 item
,参数保持不变。
我也知道 new Function()
是 eval
更好的替代品,但我也无法让它工作。对我来说更奇怪的是,该函数以前在直接在 Ajax-Call 内部评估数据属性时起作用,而没有使用像 fetchChain() 那样的准备函数。即使在阅读了有关 SO 的几个答案之后,我仍被困在这一点上。
为了完整起见,这里是 fetchData 函数:
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)
}
解决方案
我想到的一个解决方案是在将对象提供给 fetchChain()
之前准备好该对象。或者更清楚地说:在创建 prepareAjax
的上下文中。显然我更愿意直接在 fetchChain()
中处理这个过程。
错误
当如上所述执行 fetchChain
时,我在 eval 内的第二次迭代中收到错误 Unexpected Identifier
。 ([object Object]) 调试时,可以看到 obj
也更改了 data
的值。
最佳答案
为什么你不做一些类似动态获取该 obj 的事情呢?
例如:
const iterateValues = [1230,1280,4000,9000];
const getAjaxOpts = value => {
return {
ajaxOptions: [{
timeout: 10000,
type: "GET",
data: /* apply data here from value */
url: 'https://someurl.tld/target'
}],
sessionId: '<somestring>'
};
};
并进行如下迭代:
const mapped = iterateValues.map(x => getAjaxOpts(x));
// do your promise things afterwards
关于javascript - 在上下文 A 中准备上下文 B 的变量并在上下文 B 中解析它们,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53603811/