目前,我正在尝试使重复Ajax-Calls动态化,以便使我的代码更易于管理。这样做时,我有时会需要动态数据属性和-values。总是只有一个数据值发生变化,其他参数保持不变。这样做可以轻松实现承诺。

因此,这是我用作这些Ajax-Call模板的示例:

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-Call。然后,我使用eval(是,是邪恶)来解析当前上下文(fetchChain)的变量并将其提供给fetchData。这些函数是在名称空间中执行的,因此在示例中以namespace.fetchChain(prepareAjax)调用它们。

问题

该示例仅适用于一次迭代,因为即使我仅评估/修改obj,eval似乎也会永久更改tempObj,但是显然我想在每次迭代中重用模板。唯一需要解析的值是item,参数保持不变。

我也知道new Function()eval的更好替代品,但我也无法使其正常工作。对我来说更奇怪的是,该函数以前在不使用像fetchChain()这样的准备函数而直接在Ajax-Call内部评估数据属性时就可以工作了。即使在通读了关于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

09-05 19:55