【问题标题】:Why is the status undefined from an AJAX call in the context.sync() Promise chain in office.js为什么 office.js 中 context.sync() Promise 链中的 AJAX 调用未定义状态
【发布时间】:2022-01-04 13:57:41
【问题描述】:

我正在尝试构建一个 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>

为什么它没有收到状态?我该如何解决?

【问题讨论】:

  • 您能否从您的代码中创建一个Script Lab 要点并在您的问题中添加指向要点的链接?另外,https://localhost:44381/的文件的文件类型和文件内容是什么?

标签: ajax office-js


【解决方案1】:

标准承诺只有一个“返回值”。他们的.then() 回调永远不会有第二个参数。 context.sync() 返回一个标准的承诺,这就是为什么 status 没有填写你的代码。

另一方面,jQuery 的 deferred 实现做事不同,jQuery 自己的 .then() 回调可以接收多个参数。 $.ajax() 返回延迟的 jQuery。

Deferred 在很大程度上与标准 Promise 兼容,这就是您可以将它们组合在一起的原因。但是与标准的偏差,例如辅助回调参数,会丢失。

如果您需要将status 参数捕获到常规promise 中,则必须使用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() 之类的东西。

【讨论】:

  • @Sidereus 查看答案的补充。
猜你喜欢
  • 2018-11-17
  • 2021-12-16
  • 1970-01-01
  • 1970-01-01
  • 2017-04-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-06-05
相关资源
最近更新 更多