繁体   English   中英

遍历ajax调用的最佳方法是什么

[英]What's the best way to loop through ajax calls

我正在使用Sharepoint,并且有一个应用程序在网站集中创建列表(不是该应用程序!)。 创建列表不是问题。 我不会创建15列并将其添加到默认视图。 我准备了一个“配置”,其中包含列表及其字段的信息。

var ChangeRequestLogListConfig = {
    listName: 'ChangeRequestLog',
    fields: [
        { 'FieldTypeKind': 8, 'Title': 'STC Relevant', 'InternalName': 'STCrelevant', 'StaticName': 'STCrelevant' },
        { 'FieldTypeKind': 3, 'Title': 'Description/Reason', 'InternalName': 'DescriptionReason', 'StaticName': 'DescriptionReason' },
        { 'FieldTypeKind': 6, 'Title': 'Source of Change', 'InternalName': 'SourceOfChange', 'StaticName': 'SourceOfChange', 'Choices': { 'results': ['customer', 'internal'] } },
        //12 more objects like the above
    ]
}

我们遇到的问题是:使用其余资源.../ViewFields/AddViewField.../fields (使用http发布来创建新资源)仅支持一个参数,这意味着我必须进行2x15 ajax调用。

什么是执行所有这30个操作然后执行最终回调的正确方法? 当然,我知道如何遍历字段数组,我根本不知道如何以正确的方式构建最终的回调。

更新/跟进

借助一些答案,我设法构建了以下代码:

var spExecutor = new SP.RequestExecutor(_spPageContextInfo.siteAbsoluteUrl);
var requestUrl = _spPageContextInfo.siteAbsoluteUrl + "/_api/SP.AppContextSite(@target)/web/Lists/getbytitle('" + listConfig.listName + "')/fields?@target='" + hostWebUrl + "'";

//map field configs to promises
var promises = listConfig.fields.map(fieldConfig => {
    return spExecutor.executeAsync({
        url: requestUrl,
        method: "POST",
        body: JSON.stringify(fieldConfig),
        headers: {
            "accept": "application/json;odata=verbose",
            "content-type": "application/json; odata=verbose"
        },
        error: err => console.log(err)
    });
});

//Wait for all calls to be done
$.when.apply($, promises).then(callbackFn);

您可能已经看到,我没有使用$.ajax而是使用了SP.RequestExecutor 问题:这不会像jQuery的ajax那样返回promise。 这会导致计时问题(-> 15次调用,浏览器通常仅支持4个并行调用)。 上面的代码有效,如果我设置一个断点并在两次调用之间等待1-2秒,它将按预期创建所有字段。

我的后续问题:如何等待第一个调用的完成来初始化第二个,然后第三个调用,依此类推? 我不确定我是否使用正确的承诺。

使用.map将每个字段转换为Promise

var promises = ChangeRequestLogListConfig.fields.map(
    item => $.ajax( ... )
);

然后$.when等待它们全部完成:

$.when.apply($, promises).then( ... );

请注意,这将在您的浏览器允许的范围内并行启动尽可能多的AJAX请求-通常为四个。

编辑,因为您已经说过您实际上希望AJAX查询连续运行(以避免服务器409错误),我的addFieldsToList函数版本如下所示:

function addFieldsToList(listConfig) {

    return listConfig.fields.reduce(function(promise, field) {
        return promise.then(executeRequest(field, listConfig.listName));
    }, Promise.resolve(null));

}

避免传递回调,因为此函数的返回值本身就是可以链接的Promise

addFieldsToList(myConfig).then(callback);

最后,我最终这样做:

//Promise returning request
function executeRequest(fieldConfig, listName) {
    return function () {
        return new Promise(function (resolve, reject) {
            var requestUrl = _spPageContextInfo.siteAbsoluteUrl + "/_api/SP.AppContextSite(@target)/web/Lists/getbytitle('" + listName + "')/fields?@target='" + riskapp.utils.getSpHostUrl() + "'";
            var spExecutor = new SP.RequestExecutor(_spPageContextInfo.siteAbsoluteUrl);
            spExecutor.executeAsync({
                url: requestUrl,
                method: "POST",
                body: JSON.stringify(fieldConfig),
                headers: {
                    "accept": "application/json;odata=verbose",
                    "content-type": "application/json; odata=verbose"
                },
                success: resolve,
                error: reject
            });
        });
    };
}

//Add fields to list according to config
function addFieldsToList(listConfig, callback) {

    //Prepare empty/resolved promise to iterate later
    var promise = Promise.resolve(null);

    //Loop through every field 
    $.each(listConfig.fields, function (i, field) {
        promise = promise.then(executeRequest(listConfig[field], listConfig.listName));
    });

    //execute callback when all fields are created
    promise.then(callback);
}

这将按顺序而不是同时执行所有调用。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM