同步Ajax调用并执行QueryAsync Sh​​arePoint JS CSOM

时间:2014-08-20 08:15:31

标签: javascript jquery ajax sharepoint csom

使用Rest Api和JavaScript对象模型同步调用时遇到问题。

我目前正在使用客户端渲染来自定义文档库的视图,并在此自定义UI中添加一些功能。

我有一小部分内容,我在这个集合中循环,并对每个项目进行一些ajax调用。

此操作的结果是执行某些任务并在完成所有这些操作后更新我的UI以刷新我的UI并显示一些图标。

我期望只为我的前三个项目显示3个图标。

问题在于,有时它会显示所有图标,有时候会显示两个图标......随机。

我知道我的executeQueryAsync调用同步存在一些问题,我已经了解了jQuery Deferred对象,我试图使用它们但没有结果。

在您的下方,我会找到我期望的截图。

预期:

https://onedrive.live.com/redir?resid=E2C3CC814469DA54!3070&authkey=!AEf_C0XGDwfuFRY&v=3&ithint=photo%2cpng

使用延迟的好方法是什么?有人可以帮忙吗?

非常感谢

Elhmido

这是我覆盖显示的主要功能:

(function () {

var accordionContext = {};
accordionContext.Templates = {};

// Be careful when add the header for the template, because it's will break the default list view render 
accordionContext.Templates.Item = itemTemplate;

// Add OnPostRender event handler to add accordion click events and style 
accordionContext.OnPreRender = [];
accordionContext.OnPreRender.push(function () {
    $(function () {
        IsCurrentUserMemberOfGroup("TEST Owners");
        **$.when(IsUserApprover(arrayOfIDS).done(function () {
            displayIcons();
        }));**
    });
});
accordionContext.OnPostRender = [];
accordionContext.OnPostRender.push(function () {
    $(function () {
        accordionOnPostRender();
        fixColumns();
        audit.relativeUrl = _spPageContextInfo.webAbsoluteUrl;
    });
});

SPClientTemplates.TemplateManager.RegisterTemplateOverrides(accordionContext);
})();

我遇到问题的功能

function IsUserApprover(auditTab) {

var dfd = $.Deferred();

audit.tabIcons = new Array();

for (var i = 0; i < auditTab.length; i++) {

    var uri = _spPageContextInfo.webAbsoluteUrl + "/_api/web/Lists/GetByTitle('Audit')/items?$select=UserID&$filter=ID eq " + auditTab[i] + "";
    var call = $.ajax({
        url: uri,
        type: "GET",
        dataType: "JSON",
        async: false,
        headers: {
            "Accept": "application/json;odata=verbose"
        }
    });

    call.done(function (data, status, jqxhr) {

        SP.SOD.executeFunc('sp.js', 'SP.ClientContext', function () {

            var userId = data.d.results[0].UserID;
            var context = SP.ClientContext.get_current();

            var auditor = context.get_web().ensureUser(userId);
            context.load(auditor);

            //I think the problem is here because I don't know how to handle this call
            context.executeQueryAsync(userLoaded, userFailed);

            function userLoaded() {
                var auditorId = auditor.get_id();
                checkAuditorValidator(auditorId);
                dfd.resolve();
            }

            function userFailed(sender, args) {
                alert('Request failed. ' + args.get_message() + '\n' + args.get_stackTrace());

            }
        });


    });

    call.fail(function (jqxhr, status, error) {
        alert(JSON.stringify(error))
        dfd.reject();
    });

}

return dfd.promise();
}



function checkAuditorValidator(auditorId) {


var uri = _spPageContextInfo.webAbsoluteUrl + "/_api/web/Lists/GetByTitle('SecurityMgmt')/items?" +
           "$select=Auditeur/ID,Validateur/ID" +
           "&$expand=Auditeur/ID,Validateur/ID" +
           "&$filter=(Auditeur/ID eq '" + auditorId + "') and (Validateur/ID eq '" + _spPageContextInfo.userId + "')";

var call = $.ajax({
    url: uri,
    type: "GET",
    dataType: "JSON",
    async: false,
    headers: {
        "Accept": "application/json;odata=verbose"
    }
});

call.done(function (data, status, jqxhr) {

    if (data.d.results.length > 0) {

        if (audit.UserAdmin) {

            audit.tabIcons.push(true);
        }
    }
    else {
        audit.tabIcons.push(false);
    } 
});

call.fail(function (jqxhr, status, error) {
    alert(JSON.stringify(error))

});
}

1 个答案:

答案 0 :(得分:0)

Starting with Gecko 30.0 (Firefox 30.0 / Thunderbird 30.0 / SeaMonkey 2.27), synchronous requests on the main thread have been deprecated due to the negative effects to the user experience.

You should avoid synchronous ajax calls...

I had the same problem and solved by adding an id during the custom rendering of the fields (items), on the postrender call my service asynchronously and according the result edit the OnPreRender page using the previously added ids.

I also did some hacks...e.g overriding the standard function RenderItemTemplate. Yes I know, it's not very clean but it works like a charm.