用原生promise特性替代async/await解决异步的方法

41 篇文章 6 订阅
15 篇文章 1 订阅

项目开发中用到了async/await,但迁移到另一个平台时,由于该平台的架构问题使得async/await失效(无法使用)。所以必须想一些方法来替代async/await的功能,即在携带请求的异步函数中实现相对同步的方法。


首先,我们得了解promise的一种使用场景:

function runAsync(){
    var p = new Promise(function(resolve, reject){
        //做一些异步操作
        setTimeout(function(){
            console.log('执行!');
        	resolve('数据');
        }, 2000);
    });
    return p;            
}
runAsync()

把异步操作放在promise里,并且包装在一个函数中,让该函数return出这个new出来的promise
这样,在执行该函数后,就会returnpromise对象,从而可以操作promise对象的.then方法

runAsync().then(function(data){
    console.log(data);
    //这里的data,就是刚刚resolve('数据');括号里传过来的东西
    //后面可以用传过来的数据做些其他操作
    //......
});

是不是有点恍然大悟了呢?.then里获取到的data就是promise里异步操作完成后的结果,而在.then里写你在拿到data后需要执行的逻辑,不就解决了因异步拿不到数据的问题了吗~

若我们在一个函数里存在两个请求(异步操作)并且想让他们顺序执行,则可以凭借promise对象的链式操作完成:

runAsync1()
.then(function(data){
    console.log(data);
    return runAsync2();
})
.then(function(data){
    console.log(data);
    return runAsync3();
})
.then(function(data){
    console.log(data);
});

runAsync1、runAsync2、runAsync3的函数内容为:

function runAsync1(){
    var p = new Promise(function(resolve, reject){
        //做一些异步操作
        setTimeout(function(){
            console.log('异步任务1执行!');
            resolve('数据1');
        }, 1000);
    });
    return p;            
}
function runAsync2(){
    var p = new Promise(function(resolve, reject){
        //做一些异步操作
        setTimeout(function(){
            console.log('异步任务2执行!');
            resolve('数据2');
        }, 2000);
    });
    return p;            
}
function runAsync3(){
    var p = new Promise(function(resolve, reject){
        //做一些异步操作
        setTimeout(function(){
            console.log('异步任务3执行!');
            resolve('数据3');
        }, 2000);
    });
    return p;            
}

就是上面这样,第一个异步操作之后执行第二个,第二个之后执行第三个,当然如果异步操作一样的话,可以自己调用自己,也就是写个递归,后面贴代码

then方法中,你也可以直接return数据而不是Promise对象,在后面的then中就可以接收到数据了,比如:

runAsync1()
.then(function(data){
    console.log(data);
    return runAsync2();
})
.then(function(data){
    console.log(data);
    return '直接返回数据';  //这里直接返回数据
})
.then(function(data){
    console.log(data); 
});

最后贴一下修改前和修改后的代码,仅供参考:

修改前:

  async getEnergyHouse(dataId) {
      let self = this;
      let datas = {
        xdata: [],
        data: [],
        yAxisName: "",
        legendData: [],
        grid: {
          left: "5%",
          bottom: "13%",
          right: "3%",
          top: "13%",
        },
      };
      let nodeIds = [];
      let nodeidIsChi = [];
      // 获取nodeIds与子数组
      await request.get("xxx", {
          energyType: 1,
          groupType: 1,
        })
        .then((res) => {
          function getNodeids(arr) {
            for (let item of arr) {
              // 取到对应工厂
              if (item.id === dataId) {
                datas.yAxisName = item.name; // 图表名称用工厂名
                self.houseTitle = item.name; // 修改title
                if (item.children.length) {
                  item.children.forEach((chiItem) => {
                    datas.xdata.push(chiItem.name);
                    nodeIds.push(chiItem.id);
                    nodeidIsChi.push(chiItem.children.length); // 若nodeid对应的工厂子级为空,则点击后报错
                  });
                }
                break;
                // 不是对应工厂
              } else {
                // 若子数组为空,则判断下一组工厂数据
                if (item.children.length) {
                  getNodeids(item.children); // 子数组不为空,则用其递归执行该函数
                }
              }
            }
          }
          if (res.success) {
            getNodeids(res.data);
            self.nodeidIsChi = nodeidIsChi;
          }
        })
        .catch(() => {
          this.$Message.error("请求失败");
          self.loading = false;
        });
      self.loading = true;
      let params = {
        nodeType: "meterGroup",
        dimensionType: "nature",
        params: ["xxx"],
      };
      let paramsList = [
        {
          dimension: "hour",
          startTime: moment()
            .add(-1, "hour")
            .add(-1, "hour")
            .format("YYYY-MM-DD HH:mm:ss"),
          name: "上小时",
          type: "bar",
          color: "#0058F4",
        },
        {
          dimension: "day",
          startTime: moment()
            .add(-1, "day")
            .add(-1, "hour")
            .format("YYYY-MM-DD HH:mm:ss"),
          name: "当日",
          type: "bar",
          color: "#00CAFF",
        },
        {
          dimension: "month",
          startTime: moment()
            .add(-1, "month")
            .add(-1, "hour")
            .format("YYYY-MM-DD HH:mm:ss"),
          name: "当月",
          type: "line",
          color: "#10AB8C",
        },
        {
          dimension: "year",
          startTime: moment()
            .add(-1, "year")
            .add(-1, "hour")
            .format("YYYY-MM-DD HH:mm:ss"),
          name: "当年",
          type: "line",
          color: "#F6B32F",
        },
      ];
      Promise.all(
        paramsList.map((item) => {
          return request.post("xxx", {
            ...params,
            dimension: item.dimension,
            startTime: item.startTime,
            nodeIds,
            endTime: moment().add(-1, "hour").format("YYYY-MM-DD HH:mm:ss"),
          });
        })
      )
        .then((reslist) => {
          self.nodeIds = nodeIds;
          self.clickTrue = true;
          reslist.forEach((res, index) => {
            if (res.success) {
              let obj = { name: "", type: "", color: "", list: [] };
              obj.name = paramsList[index].name;
              obj.type = paramsList[index].type;
              obj.color = paramsList[index].color;
              res.data.list.forEach((item) => {
                obj.list.push(item.ydata[1]);
              });
              datas.data.push(obj);
              datas.legendData.push(obj.name);
            }
          });
          self.loading = false;
          self.chartDatas = datas;
        })
        .catch(() => {
          self.clickTrue = true;
          this.$Message.error("请求失败");
          self.loading = false;
        });
    }

修改后:


getEnergyHouse(dataId) {
      let self = this;
      let datas = {
        xdata: [],
        data: [],
        yAxisName: "",
        legend: [],
        grid: {
          left: "5%",
          bottom: "13%",
          right: "3%",
          top: "13%",
        },
      };
      let nodeIds = [];
      let nodeidIsChi = [];

      // 获取nodeIds与子数组
      function runAsync1() {
        var p = request.get("xxxx", {
          energyType: 1,
          groupType: 1,
        });
        return p;
      }

      // 获取图表数据
      function runAsync2(nodeIds) {
        let params = {
          nodeType: "meterGroup",
          dimensionType: "nature",
          params: ["xxx"],
        };
        let paramsList = [
          {
            dimension: "hour",
            startTime: moment()
              .add(-1, "hour")
              .add(-1, "hour")
              .format("YYYY-MM-DD HH:mm:ss"),
          },
          {
            dimension: "day",
            startTime: moment()
              .add(-1, "day")
              .add(-1, "hour")
              .format("YYYY-MM-DD HH:mm:ss"),
          },
          {
            dimension: "month",
            startTime: moment()
              .add(-1, "month")
              .add(-1, "hour")
              .format("YYYY-MM-DD HH:mm:ss"),
          },
          {
            dimension: "year",
            startTime: moment()
              .add(-1, "year")
              .add(-1, "hour")
              .format("YYYY-MM-DD HH:mm:ss"),
          },
        ];
        var p = Promise.all(
          paramsList.map((item) => {
            return request.post("xxxxx", {
              ...params,
              dimension: item.dimension,
              startTime: item.startTime,
              nodeIds,
              endTime: moment().add(-1, "hour").format("YYYY-MM-DD HH:mm:ss"),
            });
          })
        );
        return p;
      }

      runAsync1()
        .then((res) => {
          function getNodeids(arr) {
            for (let item of arr) {
              // 取到对应工厂
              if (item.id === dataId) {
                datas.yAxisName = item.name; // 图表名称用工厂名
                self.houseTitle = item.name; // 修改title
                if (item.children.length) {
                  item.children.forEach((chiItem) => {
                    datas.xdata.push(chiItem.name);
                    nodeIds.push(chiItem.id);
                    nodeidIsChi.push(chiItem.children.length); // 若nodeid对应的工厂子级为空,则点击后报错
                  });
                }
                break;
                // 不是对应工厂
              } else {
                // 若子数组为空,则判断下一组工厂数据
                if (item.children.length) {
                  getNodeids(item.children); // 子数组不为空,则用其递归执行该函数
                }
              }
            }
          }
          if (res.success) {
            getNodeids(res.data);
            self.nodeidIsChi = nodeidIsChi;
            self.loading = true;
          }
          return runAsync2(nodeIds);
        })
        .then((reslist) => {
          self.nodeIds = nodeIds;
          self.clickTrue = true;
          let paramsList = [
            {
              name: "上小时",
              type: "bar",
              color: "#0058F4",
            },
            {
              name: "当日",
              type: "bar",
              color: "#00CAFF",
            },
            {
              name: "当月",
              type: "line",
              color: "#10AB8C",
            },
            {
              name: "当年",
              type: "line",
              color: "#F6B32F",
            },
          ];
          reslist.forEach((res, index) => {
            if (res.success) {
              let obj = { name: "", type: "", color: "", list: [] };
              obj.name = paramsList[index].name;
              obj.type = paramsList[index].type;
              obj.color = paramsList[index].color;
              res.data.list.forEach((item) => {
                obj.list.push(item.ydata[1]);
              });
              datas.data.push(obj);
              datas.legend.push(obj.name);
            }
          });
          self.loading = false;
          self.chartDatas = datas;
        })
        .catch(() => {
          self.clickTrue = true;
          this.$Message.error("请求失败");
          self.loading = false;
        });
    },

THX~

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
引用中提到了使用async/await必须在async函数的作用域下使用,并且在使用await时要注意语法错误。而引用中介绍了async/await是ES7引入的一种异步编程方式,它提供了使用同步样式的代码异步访问资源的方式,并且不会阻塞线程。使用async/await可以简化异步编程的代码,使其更易读。同时,async/await是基于Promise的,可以通过try-catch来捕获异常。引用中还提到了多个await命令可以统一放在try...catch结构中。根据这些信息,可以得出jquery也可以使用async/await来实现异步操作。 使用jquery实现async/await的方式与使用原生JavaScript的方式基本相同。首先,确保在引入jquery之后在async函数的作用域下进行操作。然后,可以使用$.ajax来发送异步请求,并在需要等待其返回结果时使用await关键字。例如,可以将多个并发请求统一放在try...catch结构中,如下所示: ```javascript async function main() { try { const result1 = await $.ajax({ url: 'url1', method: 'GET' }); const result2 = await $.ajax({ url: 'url2', method: 'GET' }); const result3 = await $.ajax({ url: 'url3', method: 'GET' }); console.log('Final: ', result1, result2, result3); } catch (error) { console.error(error); } } main(); ``` 在上述代码中,使用$.ajax发送了三个并发请求,并使用await关键字等待每个请求的结果。最后,将三个请求的结果输出到控制台。如果发生异常,可以通过try-catch捕获并处理。这样,就可以使用jquery的async/await方式来实现异步操作了。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* [ES7 async/await](https://blog.csdn.net/JunChow520/article/details/103289715)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *3* [12. ES6 async/await 的使用](https://blog.csdn.net/ladymarry/article/details/127929395)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值