Promise

是一种异步编程的解决方案

基本使用

使用 new Promise 创建一个 Promise 实例,需要传入一个函数为参数,函数默认会传入 resolve 和 reject 两个函数。当调用了 resolve 函数后会自动调用 then 函数

  1. new Promise((resolve, reject) => {
  2. // 第一次网络请求的代码
  3. setTimeout(() => {
  4. resolve()
  5. }, 1000)
  6. }).then(() => {
  7. // 第一次拿到结果的处理代码
  8. console.log('Hello World!');
  9. return new Promise((resolve, reject) => {
  10. // 第二次网络请求的代码
  11. setTimeout(() => {
  12. resolve()
  13. }, 1000)
  14. }).then(() => {
  15. // 第二次拿到结果的处理代码
  16. console.log('Hello Vuejs');
  17. return new Promise((resolve, reject) => {
  18. // 第三次网络请求的代码
  19. setTimeout(() => {
  20. resolve()
  21. }, 1000)
  22. }).then(() => {
  23. // 第三次拿到结果的处理代码
  24. console.log('Hello Python');
  25. })
  26. })
  27. })

当往 resolve 中传入参数时,参数会传到 then 函数中,当往 reject 中传入参数时,参数会传到 catch 函数中

  1. new Promise((resolve, reject) => {
  2. setTimeout(() => {
  3. resolve(data);
  4. reject('error message');
  5. })
  6. }).then((data) => {
  7. // 用来处理成功代码
  8. console.log(data);
  9. }).catch(err => {
  10. // 用来处理失败代码
  11. console.log(err);
  12. })

其他方式

  1. new Promise((resolve, reject) => {
  2. setTimeout(() => {
  3. resolve('Hello Vuejs');
  4. reject('error message');
  5. }, 1000)
  6. // then 传入了两个参数
  7. }).then(data => {
  8. console.log(data);
  9. }, err => {
  10. console.log(err);
  11. })

三种状态

异步操作之后会有三种状态

  • pending:等待状态,比如正在进行网络请求,或者定时器没有到时间
  • fulfilled:满足状态,当我们主动回调了 resolve 时,就处于该状态,并且会回调 then()
  • rejected:拒绝状态,当我们主动回调了 reject 时,就处于该状态,并且会回调 catch()

简写方式

普通的写法

  1. new Promise((resolve, reject) => {
  2. setTimeout(() => {
  3. resolve('aaa');
  4. }, 1000);
  5. }).then(res => {
  6. console.log(res, '第一层的10行处理代码');
  7. return new Promise((resolve) => {
  8. resolve(res + '111');
  9. }).then(res => {
  10. console.log(res, '第二层的10行处理代码');
  11. return new Promise((resolve) => {
  12. resolve(res + '222');
  13. }).then(res => {
  14. console.log(res, '第三层的10行处理代码');
  15. })
  16. })
  17. })

简写之后

  1. new Promise((resolve, reject) => {
  2. setTimeout(() => {
  3. resolve('aaa');
  4. }, 1000);
  5. }).then(res => {
  6. console.log(res, '第一层的10行处理代码');
  7. // 两样也能 Promise.reject('error message)
  8. return Promise.resolve(res + '111')
  9. }).then(res => {
  10. console.log(res, '第二层的10行处理代码');
  11. return Promise.resolve(res + '222')
  12. }).then(res => {
  13. console.log(res, '第三层的10行处理代码');
  14. })

再次简写

  1. new Promise((resolve, reject) => {
  2. setTimeout(() => {
  3. resolve('aaa');
  4. }, 1000);
  5. }).then(res => {
  6. console.log(res, '第一层的10行处理代码');
  7. return res + '111'
  8. }).then(res => {
  9. console.log(res, '第二层的10行处理代码');
  10. return res + '222'
  11. }).then(res => {
  12. console.log(res, '第三层的10行处理代码');
  13. })

throw

捕获错误的另一种写法

new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve('aaa');
  }, 1000);
}).then(res => {
  console.log(res, '第一层的10行处理代码');
  throw 'error message'
}).then(res => {
  console.log(res, '第二层的10行处理代码');
  return res + '222'
}).then(res => {
  console.log(res, '第三层的10行处理代码');
}).catch(err => {
  console.log(err);
})

all 方法

当要同时获取两个异步请求结果才能进行下一步时,可以使用 all 方法

Promise.all([
new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve('result1')
  }, 2000)
}),
new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve('result2')
  }, 1000)
})
]).then(results => {
console.log(results);
})

打印结果:
image.png

axios

支持多种请求方式

  • axios(fonfig)
  • axios.request(config)
  • axios.get(url, config)
  • axios.delete(url, config)
  • axios.head(url, config)
  • axios.post(url[,data[,config]])
  • axios.put(url[,data[,config]])
  • axios.patch(url[,data[,config]])

安装和使用

安装

npm install axios —save

使用

import axios from 'axios'

axios({
  url: 'http://123.207.32.32:8000/home/multidata',
  // 默认为 get 请求
  method: 'get'
}).then(res => {
  console.log(res);
})

axios({
  // http://123.207.32.32:8000/home/data?type="pop"&page=1
  url: 'http://123.207.32.32:8000/home/data',
  // get 请求参数拼接
  params: {
    type: 'pop',
    page: 1
  },
  method: 'get'
}).then(res => {
  console.log(res);
})

post 请求 params 要换成 dta

并发请求

axios.all([
  axios({
    url: 'http://123.207.32.32:8000/home/multidata',
  }),
  axios({
    url: 'http://123.207.32.32:8000/home/data',
    params: {
      type: 'sell',
      page: 5
    }
  })
]).then(results => {
  console.log(results);
})

// results 拿到的是一个数组,这样很不方便,还有另一种写法
.then(axios.spread((res1,res2) => {
     console.log(res1);
    console.log(res2);
}))

数组的解构

ES6 中的语法

const names = ['why', 'kobe', 'james']

const [name1, name2, name3] = names

全局配置

常见的配置选项可见文档

// axios 的配置都能够提取出来
axios.defaults.baseURL = 'http://123.207.32.32:8000'
axios.defaults.timeout = 5000

// 并发请求
axios.all([
  axios({
    url: '/home/multidata',
  }),
  axios({
    url: '/home/data',
    params: {
      type: 'sell',
      page: 5
    }
  })
]).then(results => {
  console.log(results);
})

axios 实例

当数据需要向多个服务器获取时,全局配置显示不能满足需求

// 创建对应的 axios 的实例
const instance1 = axios.create({
  baseURL: 'http://123.207.32.32:8000',
  timeout: 5000
})

// 每一个实例都有自己的配置
const instance2 = axios.create({
  baseURL: 'http://222.111.33.33:8000',
  timeout: 5000
})

instance1({
  url: '/home/multidata'
}).then(res => {
  console.log(res);
})

instance2({
  url: '/home/data',
  params: {
    type: 'sell',
    page: 5
  }
}).then(res => {
  console.log(res);
})

axios 封装

封装

// src/network/request.js
import axios from 'axios';

// 不使用 export default 因为可能会封闭多个实例
export function request(config) {
  // 1.创建 axios 实例
  const instance = axios.create({
    baseURL: 'http://123.207.32.32:8000',
    timeout: 50000
  })

  // instance 返回的是一个 promise
  return instance(config)
}

使用

import { request } from "./network/request"

request({
  url: '/home/multidata'
}).then(res => {
  console.log(res);
}).catch(err => {
  console.log(err);
})

拦截器

用于我们在发送请求或者得到相应结果后,进行对应的处理

请求拦截器
**
拦截到的是的相关的配置信息

instance.interceptors.request.use(config => {
  console.log(config);
  // 如果不返回出去,发送请求时将没有 config
  return config
}, err => {
  console.log(err);
})

响应拦截器

拦截到的是响应的结果

instance.interceptors.response.use(res => {
  console.log(res);
  // 如果不返回出去,就接收不到响应的结果
  return res
}, err => {
  console.log(err);
})

better-scroll

官方文档

安装和使用

安装

npm install better-scroll —save

使用

<div class="wrapper">
  <ul class="content">
    <li>...</li>
    <li>...</li>
    ...
  </ul>
  <!-- 这里可以放一些其它的 DOM,但不会影响滚动 -->
</div>
import BScroll from '@better-scroll/core'
let bs = new BScroll('.wrapper')

侦测滚动条

import BScroll from '@better-scroll/core'
let scroll = new BScroll('.wrapper', {
  // 0,1老师不侦测实时的位置
  // 2:在手指滚动的过程中侦测,手指离开后的惯性滚动过程中不侦测
  // 3:只要是滚动,都侦测
  probeType: 3
})

// 监听事件
scroll.on('scroll', (pos) => {
      console.log(`Now position is x: ${pos.x}, y: ${pos.y}`)
})

click

BetterScroll 默认会阻止浏览器的原生 click 事件。

const bs = new BetterScroll('.wrapper', {
  click: true
})

pullUpLoad

触发时机:当底部下拉距离超过阈值(上拉加载更多)

import BetterScroll from '@better-scroll/core'

const bs = new BetterScroll('.wrapper', {
  pullUpLoad: true
})

bs.on('pullingUp', () => {
  console.log("上拉加载更多")
  // 当触发了一次该事件后将不会再次触发,必须清除事件
  bs.finishPullUp()
})

滚动原理

better-scroll 会计算出 wrapper 的高度,再计算出内容的高度,从而得出可滚动的范围。

而且商城项目中,首页的图片是异步加载的,当图片加载完之前 better-scroll 就已经把可滚动的范围计算好了

事件总线

响应式原理

image.png

const obj = {
  message: "哈哈哈",
  name: "why"
}

Object.keys(obj).forEach(item => {
  let value = obj[key]

  Object.defineProperty(obj, key, {
      set(newValue) {
        console.log("监听" + key + "改变");
      value = newValue;
    },
    get() {
        return value
    }
  })
})