getAjaxPromise(myUrl, true, myType, myContentType, mySuccessFunction, myFailureFunction, myData, true) .then(function(data)
{
//Do something with the data returned form second Ajax call.
//But data returned here is from first ajax.
});
self.getAjaxPromise = function(url, async, type, contentType, successCallback, errorCallback, data, isSecureCall)
{
if (isSecureCall) {
var tokenPromise = getTokenPromiseFromServer(); //Another Ajax call to get latest token from service
tokenPromise.then(function(tokenData) { //This then runs fine
return $.ajax({
beforeSend: function(request) {
request.setRequestHeader("authKey", tokenData.key);
},
url: url,
async: async,
type: type,
contentType: contentType,
success:
successCallback,
error: errorCallback,
data: JSON.stringify(data)
});
});
} else { //Just one ajax call
return $.ajax({
beforeSend: function(request) {
request.setRequestHeader("authKey" , "anonymous");
},
url: url,
async: async,
type: type,
contentType: contentType,
success: successCallback,
error: errorCallback,
data: JSON.stringify(data)
});
}
};
在上面的代码中,当我写.then()我得到第一个ajax调用的响应时,我不需要第一个ajax的响应,而是我想得到第一个ajax中的ajax的响应' s然后()。
我如何实现这一目标?
P.S:我编辑了这个问题,并添加了代码供参考。
答案 0 :(得分:1)
要使.then()
对外部函数起作用,您必须从该函数中返回顶级承诺,如下所示:
self.getAjaxPromise = function (url, async, type, contentType, data, isSecureCall) {
if (isSecureCall) {
// return the outer promise from the function so .then() will work
return getTokenPromiseFromServer().then(function (tokenData) { //This then runs fine
// return this ajax call to chain it to the previous promise
return $.ajax({
beforeSend: function (request) {
request.setRequestHeader("authKey", tokenData.key);
},
url: url,
async: async,
type: type,
contentType: contentType,
data: JSON.stringify(data)
});
});
} else { //Just one ajax call
return $.ajax({
beforeSend: function (request) {
request.setRequestHeader("authKey", "anonymous");
},
url: url,
async: async,
type: type,
contentType: contentType,
data: JSON.stringify(data)
});
}
};
然后,您可以像这样调用它,所有结果将在.then()
处理程序中返回,任何错误都将一直传播回来:
xxx.getAjaxPromise(...).then(function(result) {
// sucessfull result here
}, function(err) {
// error here
});
根据另一个答案的建议,创建额外的承诺或延期是考虑promise anti-pattern,因为它完全没有必要,并且经常会产生错误处理问题。相反,您可以返回已有的承诺,当您有嵌套的承诺时,您可以从.then()
处理程序中返回它,它将自动链接到第一个承诺,并将控制最终结果承诺。这将允许您的外部.then()
处理程序工作并获得正确的结果。
答案 1 :(得分:0)
我不熟悉该方法,但为什么不在jQuery Ajax调用中使用简单的jQuery Ajax调用
$.ajax({//params)}.done(() => { // other ajax call.
$.ajax({ //params}).done((result) => {//target code
});
})
答案 2 :(得分:0)
发生这种情况的原因是因为您从return getTokenPromiseFromServer()
返回了承诺。在原始ajax调用完成之前,不会执行附加到该承诺的.then
回调的return语句。因此,.then
处理程序实际上已附加到来自getTokenPromiseFromServer()
的承诺而不是嵌套$.ajax
调用。
您需要对代码进行一些重构。 jQuery提供了一种在使用$.when
https://api.jquery.com/jquery.when/执行回调之前等待承诺列表中的所有承诺的方法。根据您的需要,下面的选项可能更合适,但这是一种完成方式此
以下是一个例子:
$.when(promise1, promise2, promise3).done(function (d1, d2, d3) {
//d1 = data from promise1
//d2 = data from promise2
//d3 = data from promise3
});
当您执行代码以获得承诺时,您可以返回承诺列表,并使用$.when
等待所有承诺都解决。
如果您不关心getTokenPromiseFromServer()
外部的getAjaxPromise
,那么您可以减少重构。在这种情况下,您可以手动创建延迟,从getAjaxPromise
返回,然后在getTokenPromiseFromServer()
的回调中,您可以手动解决延迟,如此。由于您正在返回自己的延迟对象,因此.then
处理程序将附加到该处理程序而不会被执行,直到您手动解析延迟(您在嵌套$.ajax
之后执行此操作使用这种方法,你可以嵌套任意数量的ajax调用,行为也是一样的。
if (isSecureCall) {
var dfd = $.Deferred(); //create deferred
getTokenPromiseFromServer().then(function(tokenData) {
$.ajax({
beforeSend: function(request) {
request.setRequestHeader("authKey", tokenData.key);
},
url: url,
async: async,
type: type,
contentType: contentType,
success: successCallback, //Success callback runs fine, then() does not
error: errorCallback, //Error callback runs fine, then() does not
data: JSON.stringify(data)
}).then(function( data, textStatus, jqXHR ) {
dfd.resolve(data); //manually resolve the deferred which executes any callbacks attached to it
});
});
return dfd; //return the deferred, which .then() will attach to
}
编辑 ,因为人们一直在低估这个答案
正如@jfriend00在他的回答中所指出的,这被认为是一种承诺反模式,应该避免,因为它可能在更复杂的情况下引起问题。感谢他纠正我对承诺的理解。有关其他详细信息,请参阅他的答案。
相反,承诺可以通过简单地返回顶级承诺来链接。并在返回的promise上调用.then
,而不是手动创建延迟并解析它。