vue中promise的使用

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

背景

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

  

实现思路

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

遇到的问题

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

解决问题 --- 问题一

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

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

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

  1. updateKinds ({commit, state}) {
  2. return new Promise(function (resolve, reject) {
  3. axios.get('/bbg/shop/get_classify', {
  4. params: {
  5. sid:
  6. }
  7. })
  8. .then(function (response) {
  9. if (response.data.code == ) {
  10. commit(UPDATE_KINDS, response.data.data)
  11. console.log(response.data.data);
  12. resolve()
  13. }
  14. }).catch(function (error) {
  15. console.log(error);
  16. });
  17. });

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

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

解决问题 --- 问题二

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

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

  1. ar items = state.items;
  2. function getItemPromise(id) {
  3. return new Promise(function (resolve, reject) {
  4. var content = {
  5. "isSingle": ,
  6. "sbid": ,
  7. "catalog3": id,
  8. "offset": ,
  9. "pageSize":
  10. };
  11. axios.post('/bbg/goods/get_goods_list_wechat', qs.stringify({"data": JSON.stringify(content)}))
  12. .then(function (response) {
  13. if (response.data.code == ) {
  14. for (let i = ; i < response.data.data.length; i++) {
  15. commit(UPDATE_ALL_CONTENT, response.data.data[i]);
  16. }
  17. resolve();
  18. }
  19. }).catch(function (error) {
  20. console.log(error);
  21. });
  22. });
  23. }

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

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

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

  这样就相当于push了。

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

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

FIRST

  1. // first method
  2. var promise = getItemPromise(items[].id)
  3. for (let j = ; j < items.length; j++) {
  4. promise.then(function () {
  5. return getItemPromise(items[j].id);
  6. })
  7. }

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

  1. var promise = getItemPromise(items[].id);
  2. promise.then(function () {
  3. console.log("", window.performance.now());
  4. return getItemPromise(items[].id);
  5. });
  6. promise.then(function () {
  7. console.log("", window.performance.now());
  8. return getItemPromise(items[].id);
  9. });
  10. promise.then(function () {
  11. console.log("", window.performance.now());
  12. return getItemPromise(items[].id);
  13. });
  14. promise.then(function () {
  15. console.log("", window.performance.now());
  16. return getItemPromise(items[].id);
  17. });
  18. promise.then(function () {
  19. console.log("", window.performance.now());
  20. return getItemPromise(items[].id);
  21. });
  22. promise.then(function () {
  23. console.log("", window.performance.now());
  24. return getItemPromise(items[].id);
  25. });

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

方法二:

  1. // second method
  2. var somePromise = getItemPromise(items[].id);
  3. for (let k = ; k < items.length; k++) {
  4. somePromise = somePromise.then(function () {
  5. return getItemPromise(items[k].id);
  6. });
  7. }

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

  1. getItemPromise(items[].id)
  2. .then(function () {
  3. console.log("", window.performance.now());
  4. return getItemPromise(items[].id);
  5. })
  6. .then(function () {
  7. console.log("", window.performance.now());
  8.  
  9. return getItemPromise(items[].id);
  10. })
  11. .then(function () {
  12. console.log("", window.performance.now());
  13.  
  14. return getItemPromise(items[].id);
  15. })
  16. .then(function () {
  17. console.log("", window.performance.now());
  18.  
  19. return getItemPromise(items[].id);
  20. })
  21. .then(function () {
  22. console.log("", window.performance.now());
  23.  
  24. return getItemPromise(items[].id);
  25. })
  26. .then(function () {
  27. console.log("", window.performance.now());
  28.  
  29. return getItemPromise(items[].id);
  30. })
  31. .then(function () {
  32. console.log("", window.performance.now());
  33.  
  34. return getItemPromise(items[].id);
  35. })
  36. .then(function () {
  37. return getItemPromise(items[].id);
  38. })
  39. .then(function () {
  40. return getItemPromise(items[].id);
  41. })
  42. .then(function () {
  43. return getItemPromise(items[].id);
  44. })
  45. .then(function () {
  46. return getItemPromise(items[].id);
  47. })

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

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

  

vue中promise的使用的更多相关文章

  1. vue 中promise 异步请求数据

    export function getTypes(type) { return listDictItems({ code: type }).then((res) => { if (res.cod ...

  2. vue中Promise对象用法

    Promise.all([ 需要异步一起执行的方法---------先做的事 ]).then(res=>{ 后做的事(先做的事已经做好了) }) 举栗子: Promise.all([ this. ...

  3. Vue中之nextTick函数源码分析

    Vue中之nextTick函数源码分析 1. 什么是Vue.nextTick()?官方文档解释如下:在下次DOM更新循环结束之后执行的延迟回调.在修改数据之后立即使用这个方法,获取更新后的DOM. 2 ...

  4. axios在vue中的简单配置与使用

    一.axios 简介 axios 是一个基于Promise 用于浏览器和 nodejs 的 HTTP 客户端,它本身具有以下特征:https://hzzly.github.io/2017/03/12/ ...

  5. 【转】简单理解Vue中的nextTick

    前言: Vue中的nextTick涉及到Vue中DOM的异步更新,感觉很有意思,特意了解了一下.其中关于nextTick的源码涉及到不少知识,很多不太理解,暂且根据自己的一些感悟介绍下nextTick ...

  6. 简单理解Vue中的nextTick

    Vue中的nextTick涉及到Vue中DOM的异步更新,感觉很有意思,特意了解了一下.其中关于nextTick的源码涉及到不少知识,很多不太理解,暂且根据自己的一些感悟介绍下nextTick. 一. ...

  7. vue中的跨域问题

    https://segmentfault.com/a/1190000011072725(原文)   使用vue-axios和vue-resource解决vue中调用网易云接口跨域的问题 注(api很重 ...

  8. 在vue中使用import()来代替require.ensure()实现代码打包分离

    最近看到一种router的写法 import Vue from 'vue' import Router from 'vue-router' Vue.use(Router) const login = ...

  9. vue中Axios的封装和API接口的管理

    前端小白的声明: 这篇文章为转载:主要是为了方便自己查阅学习.如果对原博主造成侵犯,我会立即删除. 转载地址:点击查看 如图,面对一团糟代码的你~~~真的想说,What F~U~C~K!!! 回归正题 ...

随机推荐

  1. IIS 6.0 发布网站使用教程

    原文地址:http://wenku.baidu.com/view/95d8b49851e79b89680226aa.html

  2. Django中使用后台网站模板

    背景: 一直想自己开发一个网站,但是前端知识又不多,好在有模板可以使用,下载地址:https://download.csdn.net/download/wjgccsdn/10843808 开干:   ...

  3. spring深入了解心得

    spring 主要核心组件 :Core.上下文(Context) .实体(Bean): spring 主要由两大特色:控制反转(IOC).面向对象(AOP): spring中Core主要用于组建Bea ...

  4. c# as与is的区别

    在c#语言中关于类型的判断与转换有is和as这2种操作符,具体用法如下: is检查一个对象是否兼任与指定的类型,并返回一个Boolean值:true或false,主要,is操作符永远不会抛出异常,一下 ...

  5. 【连载】redis库存操作,分布式锁的四种实现方式[二]--基于Redisson实现分布式锁

    一.redisson介绍 redisson实现了分布式和可扩展的java数据结构,支持的数据结构有:List, Set, Map, Queue, SortedSet, ConcureentMap, L ...

  6. Delphi XE8中Android开发有用的资源!

    一,FireMonkey Component Library在XE8帮助(topics.chm)中的位置:FireMonkey Component Library,展示了FireMonkey控件在VC ...

  7. UIView 动画

    1.UIView 动画 核心动画 和 UIView 动画 的区别: 核心动画一切都是假象,并不会真实的改变图层的属性值,如果以后做动画的时候,不需要与用户交互,通常用核心动画(转场). UIView ...

  8. C语言宏的定义和宏的使用方法(#define)

    1.宏的功能介绍 在 C 语言中,可以采用命令 #define 来定义宏.该命令允许把一个名称指定成任何所需的文本,例如一个常量值或者一条语句.在定义了宏之后,无论宏名称出现在源代码的何处,预处理器都 ...

  9. redis源码分析(3)sds

    sds是redis中用来处理字符串的数据结构.sds的定义在sds.h中: typedef char *sds; 简洁明了!简明扼要!(X,玩我呢是吧!这特么不就是c中的字符串么?!).像redis这 ...

  10. POJ_2456 Aggressive cows 【二分求最大化最小值】

    题目: Farmer John has built a new long barn, with N (2 <= N <= 100,000) stalls. The stalls are l ...