从第一个电话的承诺中获取第二个电话的响应
Get second call's response from first call's promise
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 的 then() 中的 ajax。
我怎样才能做到这一点?
P.S: 我已经编辑了问题并添加了代码以供参考。
我不熟悉那个方法,但你为什么不在 jQuery Ajax 调用
中使用一个简单的 jQuery Ajax 调用
$.ajax({//params)}.done(() => { // other ajax call.
$.ajax({ //params}).done((result) => {//target code
});
})
发生这种情况的原因是因为您 return 接受了 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
});
当您执行代码以获得承诺时,您可以 return 承诺列表,并使用 $.when
等待所有承诺都得到解决。
如果您不关心 getAjaxPromise
外部的 getTokenPromiseFromServer()
,您可以通过较少的重构来逃脱。在这种情况下,您可以手动创建一个来自 getAjaxPromise
的延迟 return,然后在 getTokenPromiseFromServer()
的回调中,您可以像这样手动解决延迟。由于您正在 returning 您自己的延迟对象,因此 .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 反模式,应该避免,因为它可能会在更复杂的场景中引起问题。感谢他纠正了我对 promise 的理解。有关更多详细信息,请参阅他的回答。
相反,可以通过简单地 returning 顶级承诺来链接承诺。并在 returned 承诺上调用 .then
,而不是手动创建延迟并解决它。
要使 .then()
在外部函数上工作,您必须 return 从该函数内部像这样的顶级承诺:
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)
});
}
};
然后,您可以像这样调用它,所有结果都将 return 返回到 .then()
处理程序中,任何错误都会一直传回:
xxx.getAjaxPromise(...).then(function(result) {
// sucessfull result here
}, function(err) {
// error here
});
创建额外的 promise 或 deferred,正如另一个答案所建议的那样,考虑 promise anti-pattern 因为它完全没有必要,而且经常会产生错误处理问题。相反,你可以只 return 你已经拥有的承诺,当你有一个嵌套的承诺时,你可以 return 它来自 .then()
处理程序,它会自动链接到第一个承诺,并将控制承诺的最终结果。这将允许您的外部 .then()
处理程序工作并获得正确的结果。
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 的 then() 中的 ajax。
我怎样才能做到这一点?
P.S: 我已经编辑了问题并添加了代码以供参考。
我不熟悉那个方法,但你为什么不在 jQuery Ajax 调用
中使用一个简单的 jQuery Ajax 调用$.ajax({//params)}.done(() => { // other ajax call.
$.ajax({ //params}).done((result) => {//target code
});
})
发生这种情况的原因是因为您 return 接受了 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
});
当您执行代码以获得承诺时,您可以 return 承诺列表,并使用 $.when
等待所有承诺都得到解决。
如果您不关心 getAjaxPromise
外部的 getTokenPromiseFromServer()
,您可以通过较少的重构来逃脱。在这种情况下,您可以手动创建一个来自 getAjaxPromise
的延迟 return,然后在 getTokenPromiseFromServer()
的回调中,您可以像这样手动解决延迟。由于您正在 returning 您自己的延迟对象,因此 .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 反模式,应该避免,因为它可能会在更复杂的场景中引起问题。感谢他纠正了我对 promise 的理解。有关更多详细信息,请参阅他的回答。
相反,可以通过简单地 returning 顶级承诺来链接承诺。并在 returned 承诺上调用 .then
,而不是手动创建延迟并解决它。
要使 .then()
在外部函数上工作,您必须 return 从该函数内部像这样的顶级承诺:
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)
});
}
};
然后,您可以像这样调用它,所有结果都将 return 返回到 .then()
处理程序中,任何错误都会一直传回:
xxx.getAjaxPromise(...).then(function(result) {
// sucessfull result here
}, function(err) {
// error here
});
创建额外的 promise 或 deferred,正如另一个答案所建议的那样,考虑 promise anti-pattern 因为它完全没有必要,而且经常会产生错误处理问题。相反,你可以只 return 你已经拥有的承诺,当你有一个嵌套的承诺时,你可以 return 它来自 .then()
处理程序,它会自动链接到第一个承诺,并将控制承诺的最终结果。这将允许您的外部 .then()
处理程序工作并获得正确的结果。