• react this.setState接收参数 。写成Promise形式。以及async/await和Promise的区别


    同步编程通常来说易于调试和维护,然而,异步编程通常能获得更好的性能和更大的灵活性异步的最大特点是无需等待。“Promises”渐渐成为JavaScript里最重要的一部分,大量的新API都开始promise原理实现。

    Promise基本用法

    new Promise()构造器可以用在传统的异步任务中,就像以前 setTimeout 和 XMLHttpRequest 的用法一样。一个新的 Promise 使用 new 关键字生成,同时,这个 Promises 提供了 resolve 和 reject 函数让我们执行回调操作:(写一个模板示例)
    在这里插入图片描述

          let p = new Promise(function(resolve, reject){
            if('条件'){
              resolve('成功')
            }else{
              reject('失败')
            }
          })
          p.then(function(){})
          .catch(function(){})
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    Promise.resolve() 和 Promise.reject() 可以直接被调用。
    有时候,当判断出 promise 并不需要真正执行时,我们并不需要 使用 new 创建 Promise 对象,而是可以直接调用 Promise.resolve() 和 Promise.reject()。
    因为 promise 肯定会返回,所以,我们可以使用 then 和 catch 方法处理返回值!
    我们在写一个优化的示例

    假设我们写个 函数请求:
     function request(url, callback) {
        setTimeout(() => {
          callback({
            code: 0,
            data: "成功了",
          });
        }, 2000);
      }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    然后对其进行优化处理 此时用到了 async/await 。

    async/await

    async/await是写异步代码的新方式,它是generator的语法糖,以前的方法有回调函数和 Promise。async/await是基于Promise实现的,它不能用于普通的回调函数。
    **async/await与Promise一样,是非阻塞的。async/await使得异步代码看起来像同步代码,**这正是它的魔力所在。

    在这里插入图片描述

    在这里插入图片描述
    上图你可以看到
    async function test2() {
    const res = await request1(“/api/list”, 0); // 初始参数为0 两秒后加1 ,打印结果为1,2,3
    console.log(res);
    const res1 = await request1(“/api/list1”, res.code);
    console.log(res1);
    const res2 = await request1(“/api/list1”, res1.code);
    console.log(res2);
    }
    在这里插入图片描述

    function request(url, callback) {
            setTimeout(() => {
              callback({
                code: 0,
                data: "成功了",
              });
            }, 2000);
          }
    这两个其实一样,但是下者更为优化处理。
    function request1(url, code) {
            return new Promise((resolve) => {
              setTimeout(() => {
                resolve({
                  code: code + 1,
                  data: "成功了",
                });
              }, 2000);
            });
          }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    项目中我们会尝尝用到 异步请求 async await 以及promise 。
    当我点击了购车购物车按钮后在购物车页面。但是发现又问题看代码
    在这里插入图片描述

    在这里插入图片描述
    原本别人写的(react项目)

    //购物车数量调整
      modifyQty = async (e, record, v) => {
        const { dataSource } = this.props;
        let packNum = v;
        switch (e) {
          case 'add':
            packNum += 1;
            break;
          case 'minus':
            if (packNum > 1) {
              packNum -= 1;
              break;
            }
            return;
          case 'change':
            if (record.packNum === v) return;
        }
        this.props.setState({shopLoading: true}, async () => {
            const res = await modifyQty({
              id: record?.id,
              moq: record?.moq,
              packNum,
              unit: record?.unit
              // packNum: record?.packNum
            });
            if (res.success) {
              this.props.setState({
                shopLoading: false,
                dataSource: dataSource.map((item) => {
                  return {
                    ...item,
                    cartList: item?.cartList.map((v) => {
                      if (record.id === v?.id) {
                        return {
                          ...v,
                          packNum
                        };
                      }
                      return v;
                    })
                  };
                })
              });
            } else {
              this.props.setState({ shopLoading: false });
              ElNotification({ type: 'error', message: res.msg || res.errorMsg });
            }
          }
        );
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49

    后来我改动的

    this.props.setState( { shopLoading: true },  async () => {
      const res = await modifyQty({
       id: record?.id,
       moq: record?.moq,
       packNum,
       unit: record?.unit
     });
     if (res.success) {
       this.props.setState(
       {
    	   shopLoading: false,
           dataSource: dataSource.map((item) => {
           return {
     		...item,
    	     cartList: item?.cartList.map((v) => {
    	     if (record.id === v?.id) {
    	        return {
    		     	...v,
    		       packNum
    		        };
    		      }
    	       return v;
    		  })
          };
        })
    },
    //    计算总和显示在购物车图标上
     const total = this.props.dataSource.reduce((total, cur) => {
         return (
          total +  cur.cartList.reduce((tempTotal, cur) => {
             return tempTotal + cur.packNum;
            }, 0)
          );
         }, 0);
        
        //或者用forEach 写循环
    	 // let total = 0;
          // this.props.dataSource.forEach((cur) => {
        //   let tempTotal = 0;
        //   cur.cartList.forEach((cur) => {
         //     tempTotal = tempTotal + cur.packNum;
           //   });
           //   total = total + tempTotal;
           // }, 0);
     		console.log(total);
    	     }
         );
       } else {
        this.props.setState({ shopLoading: false });
         ElNotification({ type: 'error', message: res.msg || res.errorMsg });
        }
       }
    );
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53

    之所以写了双循环是因为接口返回是两层,一般是一层就可以了。
    在这里插入图片描述
    但是发现代码还可以优化
    写成 Promise的形式。

    写一个方法
      propsSetStateAsync(data) {
        return new Promise((resolve) => {
          this.props.setState(data, () => {
            resolve(undefined);
          });
        });
      }
      //购物车数量调整
      modifyQty = async (e, record, v) => {
        const { dataSource } = this.props;
        let packNum = v;
        switch (e) {
          case 'add':
            packNum += 1;
            break;
          case 'minus':
            if (packNum > 1) {
              packNum -= 1;
              break;
            }
            return;
          case 'change':
            if (record.packNum === v) return;
        }
        await this.propsSetStateAsync({  shopLoading: true  });
        const res = await modifyQty({
          id: record?.id,
          moq: record?.moq,
          packNum,
          unit: record?.unit
          // packNum: record?.packNum
        });
        这里逻辑是每点击加减都要请求接口,虽然扯淡,但是按照需求做吧,所以我是在请求接口后计算的。
        if (res.success) {
          await this.propsSetStateAsync({
            shopLoading: false,
            dataSource: dataSource.map((item) => {
              return {
                ...item,
                cartList: item?.cartList.map((v) => {
                  if (record.id === v?.id) {
                    return {
                      ...v,
                      packNum
                    };
                  }
                  return v;
                })
              };
            })
          });
          计算总和回赋值到购物车图表上
          const total = this.props.dataSource.reduce((total, cur) => {
            return (
              total +
              cur.cartList.reduce((tempTotal, cur) => {
                return tempTotal + cur.packNum;
              }, 0)
            );
          }, 0);
          console.log(total); 拿到这个值,
          // 计算拿到总数后,应该请求购物车接口改变数量
     	 // 这里写购物车接口并刷新数据,但是目前还没有接口就空着了
        } else {
          this.props.setState({ shopLoading: false });
          ElNotification({ type: 'error', message: res.msg || res.errorMsg });
        }
      };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69

    使用过React的应该都知道,在React中,一个组件中要读取当前状态需要访问this.state,但是更新状态却需要使用this.setState,不是直接在this.state上修改。
    setState(updater, callback)这个方法是用来告诉react组件数据有更新,有可能需要重新渲染。
    生命周期中,setState是“异步”的 。
    看到了一个不错的文章分享给你 了 看看这个介绍对我们有好处

  • 相关阅读:
    EN 14351-1门窗及配件—CE认证
    【计算机视觉 | 图像分割】arxiv 计算机视觉关于图像分割的学术速递(8 月 30 日论文合集)
    google浏览器chrome无法访问localhost等本地虚拟域名的解决方法
    简陋的nuxt2学习笔记
    学周刊杂志学周刊杂志社学周刊编辑部2022年第24期目录
    k8s学习(RKE+k8s+rancher2.x)成长系列之简配版环境搭建(四)之Helm及cert-manager安装
    python+vue+element ui致远汽车租赁系统django源码
    实战Kaggle比赛:预测房价
    【操作系统】聊聊不可中断进程和僵尸进程
    微信小程序日历插件用法-举例为(爸妈搜日历)
  • 原文地址:https://blog.csdn.net/lzfengquan/article/details/126027096