几年前,我正在修改由其他人构建的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函数作为回调的包装函数吗?我怎么把它放在一起?
答案 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);
});