【问题标题】:Making a function chainable with then()使用 then() 使函数可链接
【发布时间】:2020-07-02 04:08:31
【问题描述】:

我有一个函数,它使用 fetch() 从数据库中获取值,然后用于更新我页面上的元素:

function AjaxUpdate(_element, _url, _form_data) {
  if (!_element) return; // Nothing to update.
  if (concurrency++ == 0)
    LoadStatus(_form_data === undefined ? "Loading..." : "Processing...");
  fetch(_url, {
    method: _form_data === undefined ? "GET" : "POST",
    body: _form_data,
  })
    .then((response) => response.text())
    .then((text) => {
      if (_element.nodeName == "INPUT") _element.value = text;
      else _element.innerHTML = text;
      /* inserted */ return new Promise(function (resolve, reject) {
        resolve(text);
      });
    })
    .catch((error) => alert(error.message))
    .finally(() => {
      if (--concurrency == 0) LoadStatus("");
    });
}

我喜欢这个函数是可链接的,通过这样调用它:

const company_form = document.getElementById("company_form");
const company_properties = document.getElementById("company_properties");
const cmc_info = document.getElementById("cmc_info");
AjaxUpdate(company_properties, "company?action=edit&CompanyID=12345", new FormData(company_form))
    .then(text => { AjaxUpdate(cmc_info, "company?action=editcmc&CompanyID=12345"); });

第一次调用是 POST(更新数据库),第二次调用应该等待第一次调用完成后再开始。为此,我插入了一个return new Promise() 语句,但这并没有按预期工作。执行了初始函数调用(数据库已更新),但随后我收到一条错误消息“TypeError:函数 AjaxUpdate(...) 未定义”。 单调用版本多次使用,运行OK;当我在最后加上then() 时,它就坏了。

谁能给我一个推...?

【问题讨论】:

  • 作为旁注,我真的建议在 if/else 块周围使用大括号,即使是单行。虽然在编写时看起来不错,但在重构/维护时可能会引入相当愚蠢的错误(例如,参见 imperialviolet.org/2014/02/22/applebug.html)。
  • AjaxUpdate 不返回任何东西,更不用说承诺了。如果您执行return fetch(...).then(...),它将返回一个承诺。

标签: javascript promise


【解决方案1】:

对于获取数据的情况,您需要向 AjaxUpdate 添加一个返回语句。为了保持一致性,您也应该在 if (!_element) 的情况下返回一个承诺。

function AjaxUpdate(_element, _url, _form_data) {
  if (!_element) return Promise.resolve();
//                      ^^^^^^^^^^^^^^^^^---- MODIFIED
  if (concurrency++ == 0)
    LoadStatus(_form_data === undefined ? "Loading..." : "Processing...");
  return fetch(_url, {
//^^^^^^---- ADDED
    method: _form_data === undefined ? "GET" : "POST",
    body: _form_data,
  })
    .then((response) => response.text())
    .then((text) => {
      if (_element.nodeName == "INPUT") _element.value = text;
      else _element.innerHTML = text;
      return text;
    })
    .catch((error) => alert(error.message))
    .finally(() => {
      if (--concurrency == 0) LoadStatus("");
    });
}

【讨论】:

    【解决方案2】:

    您的return 语句在then 调用的回调 范围内。所以AjaxUpdate 实际上并没有返回那个Promise,而是一个隐含的undefined

    我建议你三种可能的解决方案。

    1. 返回fetch 承诺链结果

      function AjaxUpdate(_element, _url, _form_data) {
        if (!_element) {
          // return a dummy Promise
          return Promise.resolve(/* whatever you want as a default*/);
        }
        // ...
      
        // Returning fetch promise chain
        return fetch(...)
          .then(...)
          .then((text) => {
              // ...
              return text;
              // text will be passed from the next `then` invocation
          });
      }
      
    2. 返回一个完整的 Promise,它会在您需要时解决

      function AjaxUpdate(_element, _url, _form_data) {
        return new Promise((resolve, reject) => {
              if (!_element) {
                  resolve(/* Any default value ...*/);
              // or even reject();
              }
              // ...
      
              fetch(...)
              .then(...)
              .then((text) => {
                  // ...
                  resolve(text);
              })
              .catch(reject)
              .finally(...);
        });
      }
      
    3. 使 AjaxUpdate 异步,这样它将返回一个隐式 Promise

      async function AjaxUpdate(_element, _url, _form_data) {
          if (!_element) {
              return;
          }
      
          // ...
      
          try {
              const response = await fetch(...);
              const text = await response.text();
      
              // ...
      
              return text;
          } catch (e) {
              // ...
          }
      
          // Finally
          // ...
      }
      

    希望对你有帮助。

    【讨论】:

    • 确实有帮助!非常感谢。我只是没有看到我做错了什么。现在很清楚了!
    猜你喜欢
    • 2018-03-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-03-15
    • 1970-01-01
    • 2015-08-01
    • 2017-04-06
    • 2023-03-18
    相关资源
    最近更新 更多