如何在 React 中使用 promise 进行重构?

How to refactor with promise in React?

Visual Studio 代码建议重构代码以降低复杂性。我不知道 Promise 是什么以及如何重构下面的代码。谁能帮帮我?

const handleLoadInventory = async () => {
    try {
      const _data = await fetch('http://localhost:4000/api/v1/inventory/', {
        method: 'GET',
        headers: {
          'Content-Type': 'application/json',
          Authorization: 'Bearer ' + localStorage.getItem('token'),
        },
      })

      if (_data.status === 200) {
        const data = await _data.json()

        if (data.items.length !== 0) {
          if (inventoryData.length)
            for (let i = 1; i <= Math.ceil(data.items.length / 10); i++) {
              pagination.push(i)
            }

          for (let i = 0; i < 10 && i < data.items.length; i++) {
            showData.push(data.items[i])
          }

          setInventoryData(data.items)
        } else {
          setZeroAlert(true)
        }
      } else {
        setServerAlert(true)
        throw new Error()
      }
    } catch (err) {
      setServerAlert(true)
      console.error(err)
    }
  }

重构是将功能分解成更小单元的艺术。它背后的关键思想是通过使函数变小来使函数“显而易见”,从而使错误也变得明显。除了函数的工作原理之外,您真的不需要了解任何其他知识。

我要提取的第一部分是 fetch,因为您可能会不止一次地使用它。 Copy/pasting 您的获取代码是 bug-prone。您可能忘记设置它的 content-type 或者您可能忘记包含身份验证令牌。

因此值得把它做成自己的功能,而不仅仅是一段代码:

// This function returns a promise because fetch returns a promise:
function get (url) {
  return fetch(url, {
    method: 'GET',
      headers: {
      'Content-Type': 'application/json',
      Authorization: 'Bearer ' + localStorage.getItem('token'),
    },
  })
}

接下来是状态代码 200 的处理。您正在使用 if 块。这意味着确保所有获取数据的函数都具有相同的结构。同样,由于 copy/paste 编程,它很容易出错。

由于您正在设置状态并抛出错误,因此您可以在上面的 get() 函数中处理它:

// This function returns a promise because fetch returns a promise:
async function get (url) {
  let response = await fetch(url, {
    method: 'GET',
      headers: {
      'Content-Type': 'application/json',
      Authorization: 'Bearer ' + localStorage.getItem('token'),
    },
  })

  if (response.status !== 200) {
    throw new Error('Server response invalid')
  }
  return response
}

setServerAlert() 将由您的外部 try/catch 块处理,因为我们抛出错误。

现在您的代码已大大简化:

const handleLoadInventory = async () => {
  try {
    const _data = await get('http://localhost:4000/api/v1/inventory/')
    const data = await _data.json()

    if (data.items.length !== 0) {
      if (inventoryData.length)
        for (let i = 1; i <= Math.ceil(data.items.length / 10); i++) {
          pagination.push(i)
        }

      for (let i = 0; i < 10 && i < data.items.length; i++) {
        showData.push(data.items[i])
      }

      setInventoryData(data.items)
    } else {
      setZeroAlert(true)
    }
  } catch (err) {
    setServerAlert(true)
    console.error(err)
  }
}

就我个人而言,我什至会把 _data.json() 部分移到 get() 函数中,但我想你明白了。