typescript实时修改-远程服务批量自定义函数调用

本文内容

如果自定义函数调用远程服务,可以使用批处理模式来减少对远程服务的网络调用次数。 为了减少网络往返,您可以将所有调用批处理为对 Web 服务的单个调用。 此方法适用于重新估算电子表格时。

例如,如果有人在电子表格的 100 个单元格中使用自定义函数,然后重新计算电子表格,则自定义函数将运行 100 次并进行 100 次网络调用。 通过使用批处理模式,可以组合这些调用以在单个网络调用中完成总共 100 次估计。

重要的

请注意,Excel 自定义函数可在以下平台上使用。

Office for MacOffice 网页版

以下项目目前不支持Excel自定义函数:

查看完成的示例

要查看完整的示例,请按照本文操作并将代码示例粘贴到您自己的项目中。 例如,要为 TypeScript 创建新的自定义函数项目,请使用 Office 加载项的 Yeoman 生成器typescript实时修改,然后将本文中的所有代码添加到该项目中。 运行代码并尝试一下。

或者,下载或查看自定义函数批处理模式下的完整示例项目。 如果您想在进一步阅读之前查看完整的代码,请查看脚本文件。

按照本文所述创建批处理模式

要为自定义函数设置批处理,您需要编写三个主要代码部分。

每次 Excel 调用自定义函数时,都会向调用批处理添加一个新操作。 一。 ,计算所有操作结果并返回值的服务器代码。

在以下部分中,您将学习如何一次构建一个示例代码。 建议使用 Office Add-in Generator 的 Yeoman 生成器创建一个全新的自定义函数项目。 要创建新项目,请参阅开始开发 Excel 自定义函数。 可以使用 TypeScript 或 JavaScript。

批量调用自定义函数

typescript实时修改-远程服务批量自定义函数调用

自定义函数调用远程服务来执行操作并估计其所需的结果。 这为他们提供了一种将每个请求的操作批量存储的方法。 稍后,您将了解如何创建 _pushOperation 函数来批处理此操作。 首先,查看下面的代码示例,了解如何从自定义函数调用 _pushOperation。

在下面的代码中,自定义函数执行加法,但实际估计取决于远程服务。 它调用 _pushOperation,后者又将该操作与其他操作一起批处理到远程服务。 它将操作命名为“div2”。 您可以使用任何您想要的操作命名方案,只要远程服务使用相同的方案(稍后将详细介绍远程服务方面)。 据悉,远程服务运行计算所需的参数也会被传递。

添加div2自定义功能

将以下代码添加到functions.js或functions.ts文件中(取决于您使用的是JavaScript还是TypeScript)。

/**
 * Divides two numbers using batching
 * @CustomFunction
 * @param dividend The number being divided
 * @param divisor The number the dividend is divided by
 * @returns The result of dividing the two numbers
 */
function div2(dividend, divisor) {
  return _pushOperation("div2", [dividend, divisor]);
}

添加全局变量以跟踪批量请求

接下来,将两个全局变量添加到functions.js或functions.ts文件中。 _isBatchedRequestScheduled 对于定时批量调用远程服务尤其重要。

let _batch = [];
let _isBatchedRequestScheduled = false;

_pushOperation添加功能

Excel调用自定义函数时,需要将操作推送到批处理列表中。 以下 _pushOperation 函数代码演示了如何从自定义函数添加新操作。 它创建一个新的批处理条目,创建一个新的承诺来解决或拒绝相应的操作typescript实时修改,并将该条目推送到批处理列表中。

此代码检测是否安排了批次。 在此示例中,每个位批次计划每 100 纳秒运行一次。 该值可以根据需要进行调整。 该值越大,发送到远程服务的批次越大,用户等待查看结果的时间就越长。 较低的值往往会向远程服务发送更多批次,但为用户提供更快的响应时间。

该函数创建一个 invokingEntry 对象,其中包含要运行的操作的字符串名称。 例如,如果您有两个名为“乘法”和“除法”的自定义函数,则可以将它们重用为批处理条目上的操作名称。 args 保存从 Excel 传递到自定义函数的参数。 最后,resolve 或reject 方法存储包含远程服务返回的信息的promise。

将以下代码添加到functions.js或functions.ts文件中。

// This function encloses your custom functions as individual entries,
// which have some additional properties so you can keep track of whether or not
// a request has been resolved or rejected.
function _pushOperation(op, args) {
  // Create an entry for your custom function.
  console.log("pushOperation");
  const invocationEntry = {
    operation: op, // e.g., sum
    args: args,
    resolve: undefined,
    reject: undefined,
  };
  // Create a unique promise for this invocation,
  // and save its resolve and reject functions into the invocation entry.
  const promise = new Promise((resolve, reject) => {
    invocationEntry.resolve = resolve;
    invocationEntry.reject = reject;
  });
  // Push the invocation entry into the next batch.
  _batch.push(invocationEntry);
  // If a remote request hasn't been scheduled yet,
  // schedule it after a certain timeout, e.g., 100 ms.
  if (!_isBatchedRequestScheduled) {
    console.log("schedule remote request");
    _isBatchedRequestScheduled = true;
    setTimeout(_makeRemoteRequest, 100);
  }
  // Return the promise for this invocation.
  return promise;
}

发出远程请求

_makeRemoteRequest 函数的目的是将一批操作传递给远程服务,然后将结果返回给每个自定义函数。 它首先创建批处理链表的副本。 这样,来自 Excel 的并发自定义函数调用可以立即开始新字段中的批处理。 然后,该副本将转换为不包含承诺信息的更简单的字段。 将此类承诺传递给远程服务是没有意义的,因为它们不起作用。 _makeRemoteRequest 将根据远程服务返回的内容拒绝或解决每个承诺。

将以下代码添加到functions.js或functions.ts文件中。

// This is a private helper function, used only within your custom function add-in.
// You wouldn't call _makeRemoteRequest in Excel, for example.
// This function makes a request for remote processing of the whole batch,
// and matches the response batch to the request batch.
function _makeRemoteRequest() {
  // Copy the shared batch and allow the building of a new batch while you are waiting for a response.
  // Note the use of "splice" rather than "slice", which will modify the original _batch array
  // to empty it out.
  try{
  console.log("makeRemoteRequest");
  const batchCopy = _batch.splice(0, _batch.length);
  _isBatchedRequestScheduled = false;
  // Build a simpler request batch that only contains the arguments for each invocation.
  const requestBatch = batchCopy.map((item) => {
    return { operation: item.operation, args: item.args };
  });
  console.log("makeRemoteRequest2");
  // Make the remote request.
  _fetchFromRemoteService(requestBatch)
    .then((responseBatch) => {
      console.log("responseBatch in fetchFromRemoteService");
      // Match each value from the response batch to its corresponding invocation entry from the request batch,
      // and resolve the invocation promise with its corresponding response value.
      responseBatch.forEach((response, index) => {
        if (response.error) {
          batchCopy[index].reject(new Error(response.error));
          console.log("rejecting promise");
        } else {
          console.log("fulfilling promise");
          console.log(response);
          batchCopy[index].resolve(response.result);
        }
      });
    });
    console.log("makeRemoteRequest3");
  } catch (error) {
    console.log("error name:" + error.name);
    console.log("error message:" + error.message);
    console.log(error);
  }
}

根据自己的解决方案更改_makeRemoteRequest

_makeRemoteRequest 函数调用 _fetchFromRemoteService,正如您稍后将看到的,它只是代表远程服务的模拟。 这使得学习和运行本文中的代码变得更加容易。 并且,如果将此代码用于实际的远程服务,则应进行以下修改。

处理远程服务上的批量调用

最后一步是处理远程服务中的批量调用。 下面的代码示例显示了 _fetchFromRemoteService 函数。 该函数将每一位操作解包,执行指定的操作,并返回结果。 出于学习目的,在本文中,_fetchFromRemoteService 函数适合在 Web 加载项中运行并模拟远程服务。 可以将此代码添加到functions.js或functions.ts文件中,以便可以探索和运行本文中的所有代码,而无需设置实际的远程服务。

将以下代码添加到functions.js或functions.ts文件中。

// This function simulates the work of a remote service. Because each service
// differs, you will need to modify this function appropriately to work with the service you are using. 
// This function takes a batch of argument sets and returns a promise that may contain a batch of values.
// NOTE: When implementing this function on a server, also apply an appropriate authentication mechanism
//       to ensure only the correct callers can access it.
async function _fetchFromRemoteService(requestBatch) {
  // Simulate a slow network request to the server.
  console.log("_fetchFromRemoteService");
  await pause(1000);
  console.log("postpause");
  return requestBatch.map((request) => {
    console.log("requestBatch server side");
    const { operation, args } = request;
    try {
      if (operation === "div2") {
        // Divide the first argument by the second argument.
        return {
          result: args[0] / args[1]
        };
      } else if (operation === "mul2") {
        // Multiply the arguments for the given entry.
        const myResult = args[0] * args[1];
        console.log(myResult);
        return {
          result: myResult
        };
      } else {
        return {
          error: `Operation not supported: ${operation}`
        };
      }
    } catch (error) {
      return {
        error: `Operation failed: ${operation}`
      };
    }
  });
}
function pause(ms) {
  console.log("pause");
  return new Promise((resolve) => setTimeout(resolve, ms));
}

根据自己的实时远程服务更改_fetchFromRemoteService

要将函数 _fetchFromRemoteService 更改为在实时远程服务中运行,请进行以下修改。

下一步

了解可在自定义函数中使用的各种类型的参数。 或者查看通过自定义函数进行 Web 调用旁边的基础知识。

也可以看看

收藏 (0) 打赏

感谢您的支持,我会继续努力的!

打开微信/支付宝扫一扫,即可进行扫码打赏哦,分享从这里开始,精彩与您同在
点赞 (0)

悟空资源网 typescript typescript实时修改-远程服务批量自定义函数调用 https://www.wkzy.net/game/191751.html

常见问题

相关文章

官方客服团队

为您解决烦忧 - 24小时在线 专业服务