如何修改JS代码以重用API调用?

时间:2017-03-01 16:56:12

标签: javascript api knockout.js

几年前,我正在修改由其他人构建的Web应用程序。在其中,他在JS中构建了一个API函数,在调用时,它将从SharePoint中提取数据。我正在为应用程序添加一个功能,并需要执行另一个API调用来检索一些不同的数据。到目前为止,我还没有能够弄清楚如何修改代码,以便等待ajax调用完成。我所做的所有研究都表明我应该使用回调来实现这一目标,但我不确定如何正确实现它。

现有代码如下所示:

API = function(apiFunction, dataToPost, successCallback) {
    var baseApiUrl = '/SomeWebApp/API/';
    var apiUrl = baseApiUrl + apiFunction;

    $.ajax({
        url: apiUrl,
        data: JSON.stringify(dataToPost),
        dataType: "json",
        type: "POST",
        contentType: "application/json; charset=utf-8",
        dataFilter: function(data) { return data; },
        success: successCallback,
        error: function(XMLHttpRequest, textStatus, errorThrown) {
            alert('Error calling webservice: ' + apiFunction);
        }
    });
}

对API的调用是:

API('Lists.asmx/GetStuff', dataToPost, function(data) {
    var options = [];

    $.each(data.d, function(index, value) {
        options.push(new Category(value.Field, value.AnotherField, value.YetAnotherField));
    });

    var viewModel = new ViewModel(options);

    ko.applyBindings(viewModel);
});

我需要做的是执行第二个API调用以检索其余数据,然后创建视图模型,并将两组数据传递给它。

我尝试过的事情:

  • options移到回调函数之外,但似乎因为它是异步的,脚本不会等待返回数据。如果确实有效,我可以将ko.ApplyBindings移到回调函数之外,然后用两组数据创建新的视图模型

  • 将API调用分配给变量,并使回调函数返回options。例如:

    var x = API('Lists.asmx/GetStuff', dataToPost, function(data) {
        var options = [];
    
        $.each(data.d, function(index, value) {
            options.push(new Category(value.Field, value.AnotherField, value.YetAnotherField));
        });
    
        return options;
    });
    

修改代码以实现此目的的最佳方法是什么?我应该创建一个包含API函数作为回调的包装函数吗?我怎么把它放在一起?

1 个答案:

答案 0 :(得分:1)

快速而肮脏的解决方案是将第二个API调用放在第一个API调用的回调函数中。返回语句实际上不会在异步函数中执行任何操作,除非它返回" promise" (见选项2)。

API('Lists.asmx/GetStuff', dataToPost, function(data) {
    var options = [];

    $.each(data.d, function(index, value) {
        options.push(new Category(value.Field, value.AnotherField, value.YetAnotherField));
    });

    API('Lists/asmx/GetStuff2', secondDataToPost, function(data2){            
        var viewModel = new ViewModel(options, data2);
        ko.applyBindings(viewModel);
    });
});

选项2 - 由于您的API函数已经使用jQuery来处理ajax,您可以更改它以返回ajax调用的结果,这是一种延迟对象,您可以在其上调用.done来附加回调方法。 jquery-deferred-and-promise walkthrough

API = function(apiFunction, dataToPost, successCallback) {
    var baseApiUrl = '/SomeWebApp/API/';
    var apiUrl = baseApiUrl + apiFunction;

    return $.ajax({
        ...
    });
}

通过在对象上使用.done方法,返回的延迟对象可以与传入的回调类似地使用。

API('Lists.asmx/GetStuff', dataToPost).done(function(data) {
    callback stuff...
});

这有点灵活,可以让你像下面那样进行链接和同步执行,同时两个api调用都被发送,而不必在发送第二个调用之前等待第一个调用的响应。 / p>

$.when(
    API('Lists.asmx/GetStuff', dataToPost),
    API('Lists.asmx/GetStuff2', dataToPost2)
).done(function(data1, data2) {
    var options = [];

    $.each(data.d, function(index, value) {
        options.push(new Category(value.Field, value.AnotherField, value.YetAnotherField));
    });

    var viewModel = new ViewModel(options, data2);
    ko.applyBindings(viewModel);
});