【问题标题】:Is there a way to know if a promise is not being resolved?有没有办法知道一个承诺是否没有得到解决?
【发布时间】:2021-05-01 06:42:59
【问题描述】:

我有这个代码:

let [totalPromos, setTotalPromos] = useState(0);

for (let item of cart.items){
    let response = await api.get('/products/' + item.id);
    let price = response.data.price;
    let promotion = response.data.promotions[0];
    setTotalPromos(totalPromos + 1);
}

我在购物车中有 2 件商品,我用 axios 调用了一个 api 以实现其促销。我无法总结我产品的促销总数。该值仅获得此代码中的最终值,即 1。我做错了什么?

【问题讨论】:

标签: reactjs react-native ecmascript-6 react-hooks ecmascript-2016


【解决方案1】:

我认为你应该像这样使用这段代码。

let [totalPromos, setTotalPromos] = useState(0);

for (let item of cart.items){
    api.get('/products/' + item.id)
    .then((response) => {
      if (response) {
        let price = response.data.price;
        let promotion = response.data.promotions[0];
        setTotalPromos(totalPromos + 1);
        return;
      }
      console.log("Not a valid response");
    })
    .catch((error) => {  // Failed to resolve then go to chach block
      console.log(error);
    }
}

或者你可以使用

async function getProductById() {
  try {
    var response = await api.get('/products/' + item.id);
     if (response) {
        let price = response.data.price;
        let promotion = response.data.promotions[0];
        setTotalPromos(totalPromos + 1);
        return;
      }
      console.log("Not a valid response");
  } catch (error) {
    console.error(error);
  }
}

你可以使用你想要的,但我个人更喜欢第一个。

【讨论】:

    【解决方案2】:

    将异步调用移至useEffect()。使用Functional updates 选项设置状态,所以useEffect() 不会依赖totalPromos,因为它会在每次渲染时重新启动(渲染是由设置状态引起的)。

    <script crossorigin src="https://unpkg.com/react@17/umd/react.development.js"></script>
    <script crossorigin src="https://unpkg.com/react-dom@17/umd/react-dom.development.js"></script>
    
    <script src="https://unpkg.com/@babel/standalone@7.12.12/babel.min.js"></script>
    
    
    <div id="root"></div>
    
    <script type="text/jsx">
    
      const { useState, useEffect } = React;
    
      const Demo = ({ items }) => {
        const [totalPromos, setTotalPromos] = useState(0);
    
        useEffect(async() => {
          for (const item of items){
            const price = await get(item);
            setTotalPromos(totalPromos => totalPromos + price);
          }
        }, [items]);
    
        return (
          <div>
            {totalPromos}
          </div>
        );
      }
    
      const items = [1, 2, 3, 4];
    
      ReactDOM.render(
        <Demo items={items} />,
        root
      );
    
      // mock async get
      function get(item) {
        return new Promise(resolve => setTimeout(() => resolve(item), 100));
      }
    
    </script>

    【讨论】:

    • 伙计,我真的很感激!设置 setTotalPromos(totalPromos => totalPromos + price) 有效!我只是不明白为什么我需要使用“=>”进行设置?
    • 如果useEffects() 依赖列表中的任何内容发生变化(并且totalPromos 每次都会更改),该函数将被再次调用。为了防止这种情况,您可以使用功能更新。设置状态接收的不是获取值,而是创建新状态。该函数使用当前值 (totalPromos) 调用,您不必显式传递它。我在答案中添加了一个链接。
    猜你喜欢
    • 2022-01-16
    • 1970-01-01
    • 2019-10-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-08-20
    • 2015-01-18
    相关资源
    最近更新 更多