vue中promise的使用

摘要:
vue中promise的使用promise是处理异步的利器,在之前的文章《ES6之promise》中,我详细介绍了promise的使用,在文章《js动画实现&&回调地狱&&promise》中也提到了promise的then的链式调用,这篇文章主要是介绍在实际项目中关于异步我遇到的一些问题以及解决方法,由此来加深对promise的进一步理解。解决问题---问题一针对问题一,最好的方式还是使用promise,大致实现如下:getClassify:function(){varthat=this;//使用promise处理异步。

vue中promise的使用

promise是处理异步的利器,在之前的文章《ES6之promise》中,我详细介绍了promise的使用, 在文章《js动画实现&&回调地狱&&promise》中也提到了promise的then的链式调用, 这篇文章主要是介绍在实际项目中关于异步我遇到的一些问题以及解决方法,由此来加深对promise的进一步理解。

背景

进入商品页,商品页的左侧是分类,右侧是具体的商品,一旦进入商品页,就把所有分类的商品请求出来,注意: 必须要按照顺序。

实现思路

在商品页, created 钩子函数触发获取分类的http请求,请求到结果后,开始请求所有的具体商品并渲染。

遇到的问题

  • 由于请求商品分类是异步的, 怎么判断异步请求完成, 也就是说请求具体商品的时机是什么时候。
  • 获取到所有的商品必须发送请求,请求时异步的,怎么保证能够按照顺序获取到。

解决问题--- 问题一

针对问题一,最好的方式还是使用promise,大致实现如下:

getClassify: function () {
        var that = this;
        //使用promise处理异步。
        this.updateKinds().then(function () {
          console.log("获取分类结束!");
          that.updateAllContent();
        });
      },

其中getClassify是在created时就会调用的,而updateKinds是actions中的方法,我们先看看actions中是怎么写的:

updateKinds ({commit, state}) {
      return newPromise(function (resolve, reject) {
        axios.get('/bbg/shop/get_classify', {
          params: {
            sid:  13729792
          } 
        })
        .then(function (response) {
          if (response.data.code == 130) {
            commit(UPDATE_KINDS, response.data.data)
            console.log(response.data.data);
            resolve()
          }
        }).catch(function (error) {
          console.log(error);
        });
      });

即返回一个promise,当请求到数据,并且commit之后,我们就额可以resolve()了,这样,就可以在then中执行获取所有内容的方法了。

虽然实现起来比较简单,但是这个思想更好。

解决问题 --- 问题二

在问题一中,我们看到resolve之后就可以调用updateAllContent() 了,那么这个应该怎么写呢?

首先可以确定的是: 因为需要请求的分类不只一个,所以要使用promise, 并且一定要返回一个promise,这样才能继续链式调用,其中一部分如下:

ar items =state.items;
      function getItemPromise(id) {
        return newPromise(function (resolve, reject) {
          var content ={
            "isSingle": 1,
            "sbid": 13729792,
            "catalog3": id,
            "offset": 0,
            "pageSize": 10
          };
          axios.post('/bbg/goods/get_goods_list_wechat', qs.stringify({"data": JSON.stringify(content)}))
          .then(function (response) {
            if (response.data.code == 626) {
              for (let i = 0; i < response.data.data.length; i++) {
                commit(UPDATE_ALL_CONTENT, response.data.data[i]);
              }
              resolve();
            }
          }).catch(function (error) {
            console.log(error);
          });
        });
      }

即调用这个函数,传入一个分类的id,然后就可以发送请求了,获取到数据之后,就把数据插入到 内容的数组中, 最后resolve()还告诉then可以执行了。

注意: 如何更新一个数组呢?

[UPDATE_ALL_CONTENT] (state, item) {
      state.contentItems =[...state.contentItems, Object.assign({}, item)];
    },

这样就相当于push了。

上面的这个函数的意义在于封装请求,那么对于请求多个时,如何做到呢?

我之前尝试了下面两种方法:

FIRST

    //first method
      var promise = getItemPromise(items[0].id)
      for (let j = 1; j < items.length; j++) {
        promise.then(function () {
          returngetItemPromise(items[j].id);
        })
      }

思路就是先请求第一个分类,然后循环,实际上和下面的效果是一样的:

var promise = getItemPromise(items[0].id);
      promise.then(function () {
        console.log("1", window.performance.now());
        return getItemPromise(items[1].id);
      });
      promise.then(function () {
        console.log("2", window.performance.now());
        return getItemPromise(items[2].id);
      });
      promise.then(function () {
        console.log("3", window.performance.now());
        return getItemPromise(items[3].id);
      });
      promise.then(function () {
        console.log("4", window.performance.now());
        return getItemPromise(items[4].id);
      });
      promise.then(function () {
        console.log("5", window.performance.now());
        return getItemPromise(items[5].id);
      });
      promise.then(function () {
        console.log("6", window.performance.now());
        return getItemPromise(items[6].id);
      });

问题: 通过这样的方法最终请求的数据是可以请求到的,但是顺序并没有按照我们预想的思路来执行,因为这样的执行方式会在getItemPromise执行之后就立即同时执行后面几个then,所以最终得到的顺序是不能确定的。

方法二:

      //second method
      var somePromise = getItemPromise(items[0].id);
      for (let k = 1; k < items.length; k++) {
          somePromise =somePromise.then(function () {
          returngetItemPromise(items[k].id);
       });
      }

这种方法的结构类似于下面这样:

getItemPromise(items[0].id)
      .then(function () {
        console.log("1", window.performance.now());
        return getItemPromise(items[1].id);
      })
      .then(function () {
        console.log("2", window.performance.now());
        return getItemPromise(items[2].id);
      })
      .then(function () {
        console.log("3", window.performance.now());
        return getItemPromise(items[3].id);
      })
      .then(function () {
        console.log("4", window.performance.now());
        return getItemPromise(items[4].id);
      })
      .then(function () {
        console.log("5", window.performance.now());
        return getItemPromise(items[5].id);
      })
      .then(function () {
        console.log("6", window.performance.now());
        return getItemPromise(items[6].id);
      })
      .then(function () {
        console.log("7", window.performance.now());
        return getItemPromise(items[7].id);
      })
      .then(function () {
        return getItemPromise(items[8].id);
      })
      .then(function () {
        return getItemPromise(items[9].id);
      })
      .then(function () {
        return getItemPromise(items[10].id);
      })
      .then(function () {
        return getItemPromise(items[11].id);
      })

这样请求得到的顺序就是相同的了。 但是通过for循环,不论分类有多少,我们都可以请求到。

也就是说,通过链式调用的方式,即.then().then()这样才会在一个异步执行完之后执行下一个,值得注意。

免责声明:文章转载自《vue中promise的使用》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇什么是形式验证?windows和iis对应版本关系下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

基于Idea从零搭建一个最简单的vue项目

一、需要了解的基本知识 node.js Node.js是一个Javascript运行环境(runtime),发布于2009年5月,由Ryan Dahl开发,实质是对Chrome V8引擎进行了封装。Node.js对一些特殊用例进行优化,提供替代的API,使得V8在非浏览器环境下运行得更好。V8引擎执行Javascript的速度非常快,性能非常好。 No...

vue 强制刷新子组件

原因:因为父组件有缓存等因素,子组件创建后没有释放,传入参数无效,使用v-if的特性(销毁和重建)可以强制刷新子组件 <el-drawer ref="detailTable" :title="detailTitle" :append-to-body="true" :visible.sync="d...

Dubbo封装rest服务返回结果

由于Dubbo服务考虑到一个是给其他系统通过RPC调用,另外一个是提供HTTP协议本身系统的后台管理页面,因此Dubbo返回参数在rest返回的时候配置拦截器进行处理。 在拦截器中,对返回参数封装成如下对象,并统一输出到前端。 1 packagecom.wjs.common.web; 2 3 importorg.apache.commons.lang....

VUE 在一个组件中引用另外一个组件的两种方式

背景:比如在一个vue写成的页面中,想要使用一个vue完成的表格组件(这个表格组件也是一个XXX.vue文件),具体的怎么在一个文件中引入需要使用的那部分内容,比如前面的表格、比如某个饼图图表什么的。 下面有两种方法: 方法一:代码如下     <template> <div> <!-- 3.在template中就可以直...

Comet 反Ajax: jQuery与PHP实现Ajax长轮询

原文地址(http://justcode.ikeepstudying.com/2016/08/comet-%E5%8F%8Dajax-%E5%9F%BA%E4%BA%8Ejquery%E4%B8%8Ephp%E5%AE%9E%E7%8E%B0ajax%E9%95%BF%E8%BD%AE%E8%AF%A2longpoll/) 页面代码: <!DOCTY...

promise使用场景

1、使用场景:在一个房源列表里,点击某一条房源里的图片实现看大图效果。(vue2) 问题:使用vue-preview查看大图时需要知道图片宽高,但是接口没有返回,所以需要使用Image对象来获取图片宽高。 arr.forEach((val, indexs) =>{ let img = newImage() img.addEventL...