为什么 office.js 中 context.sync() Promise 链中的 AJAX 调用未定义状态
Why is the status undefined from an AJAX call in the context.sync() Promise chain in office.js
我正在尝试构建一个 Excel 加载项,它使用 AJAX 根据内容从另一台服务器获取数据。我创建了以下简单原型,它进行简单的 get 调用并将结果写入单元格。 AJAX 调用尚未使用 Excel 的内容,但将来会用到。
Excel.run(function (context) {
let sourceRange = context.workbook.getSelectedRange().load("values, rowCount, columnCount");
return context.sync()
.then(function() {
return $.ajax("https://localhost:44381/");
})
.then(function (data, status) {
let values = [[ "Result:" + data + status ]];
sourceRange.values = values;
})
.then(context.sync);
}).catch(errorHandler);
除了始终未定义的状态外,一切似乎都正常。这很奇怪,因为数据是正确的。我已经在 context.sync() 承诺链之外尝试过它,它工作得很好。状态应该是“成功”,并且它确实与像这样的承诺链中的 then(function(data, status)...
一起工作。我已经用下面的代码试过了:
<!DOCTYPE html>
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<script>
$(document).ready(function(){
$("button").click(function(){
$.ajax("https://localhost:44381/")
.then(function(data, status){
alert(data + status);
})
.then(function() {
return $.ajax("https://localhost:44381/");
})
.then(function(data, status){
alert(data + status);
});
});
});
</script>
</head>
<body>
<button>Send an HTTP GET request to a page and get the result back</button>
</body>
</html>
为什么收不到状态?我该如何解决?
标准承诺只有一个“return 值”。他们的 .then()
回调永远不会有第二个参数。 context.sync()
return 是一个标准的承诺,这就是为什么 status
没有填写在您的代码中。
另一方面,jQuery 的 deferred 实现做事不同,jQuery 自己的 .then()
回调 can 接收多个参数。 $.ajax()
return 推迟 jQuery。
延迟在很大程度上与标准承诺兼容,这就是为什么您可以首先将它们结合起来。但是与标准的偏差,如辅助回调参数,将丢失。
如果您需要将 status
参数捕获到常规承诺中,则必须使用 jQuery 自己的 .then()
作为助手:
return context.sync()
.then(() => {
return $.ajax("https://localhost:44381/").then((data, status) => {
return {data, status};
});
}).then(response => {
// now you have response.data and response.status
});
此处 jQuery 的 .then()
通过将各个参数包装在对象 {data: ..., status: ...}
中来生成单个值,并将其传递给封闭的本机 promise。
如果您更频繁地需要它,您可以围绕 $.ajax()
制作一个包装器。
function jqAjax() {
return new Promise((resolve, reject) =>
$.ajax.apply($, arguments).then(
(data, status, jqXHR) => resolve({data, status, jqXHR}),
(jqXHR, status, error) => reject({error, status, jqXHR})
)
);
}
这将为您提供标准的承诺行为,作为交换,您将无法访问 jQuery 自己的延迟 API,即 .done()
或 .always()
之类的东西。
我正在尝试构建一个 Excel 加载项,它使用 AJAX 根据内容从另一台服务器获取数据。我创建了以下简单原型,它进行简单的 get 调用并将结果写入单元格。 AJAX 调用尚未使用 Excel 的内容,但将来会用到。
Excel.run(function (context) {
let sourceRange = context.workbook.getSelectedRange().load("values, rowCount, columnCount");
return context.sync()
.then(function() {
return $.ajax("https://localhost:44381/");
})
.then(function (data, status) {
let values = [[ "Result:" + data + status ]];
sourceRange.values = values;
})
.then(context.sync);
}).catch(errorHandler);
除了始终未定义的状态外,一切似乎都正常。这很奇怪,因为数据是正确的。我已经在 context.sync() 承诺链之外尝试过它,它工作得很好。状态应该是“成功”,并且它确实与像这样的承诺链中的 then(function(data, status)...
一起工作。我已经用下面的代码试过了:
<!DOCTYPE html>
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<script>
$(document).ready(function(){
$("button").click(function(){
$.ajax("https://localhost:44381/")
.then(function(data, status){
alert(data + status);
})
.then(function() {
return $.ajax("https://localhost:44381/");
})
.then(function(data, status){
alert(data + status);
});
});
});
</script>
</head>
<body>
<button>Send an HTTP GET request to a page and get the result back</button>
</body>
</html>
为什么收不到状态?我该如何解决?
标准承诺只有一个“return 值”。他们的 .then()
回调永远不会有第二个参数。 context.sync()
return 是一个标准的承诺,这就是为什么 status
没有填写在您的代码中。
jQuery 的 deferred 实现做事不同,jQuery 自己的 .then()
回调 can 接收多个参数。 $.ajax()
return 推迟 jQuery。
延迟在很大程度上与标准承诺兼容,这就是为什么您可以首先将它们结合起来。但是与标准的偏差,如辅助回调参数,将丢失。
如果您需要将 status
参数捕获到常规承诺中,则必须使用 jQuery 自己的 .then()
作为助手:
return context.sync()
.then(() => {
return $.ajax("https://localhost:44381/").then((data, status) => {
return {data, status};
});
}).then(response => {
// now you have response.data and response.status
});
此处 jQuery 的 .then()
通过将各个参数包装在对象 {data: ..., status: ...}
中来生成单个值,并将其传递给封闭的本机 promise。
如果您更频繁地需要它,您可以围绕 $.ajax()
制作一个包装器。
function jqAjax() {
return new Promise((resolve, reject) =>
$.ajax.apply($, arguments).then(
(data, status, jqXHR) => resolve({data, status, jqXHR}),
(jqXHR, status, error) => reject({error, status, jqXHR})
)
);
}
这将为您提供标准的承诺行为,作为交换,您将无法访问 jQuery 自己的延迟 API,即 .done()
或 .always()
之类的东西。