Promise 对象
看看一个例子
function fn1() {
setTimeout(()=>{
console.log('fn1')
}, 1000)
}
function fn2() {
setTimeout(()=>{
console.log('fn2')
}, 1000)
}
function fn3() {
setTimeout(()=>{
console.log('fn3')
}, 1000)
}
对于以上代码如何实现: 1秒钟之后输出 fn1, 再过疫苗输出 fn2, 再过1秒输出 fn3 ?
可如下改装:
function fn1(callback) {
setTimeout(()=>{
console.log('fn1')
callback()
}, 1000)
}
function fn2(callback) {
setTimeout(()=>{
console.log('fn2')
callback()
}, 1000)
}
function fn3() {
setTimeout(()=>{
console.log('fn3')
}, 1000)
}
fn1(function(){
fn2(function(){
fn3()
})
})
回调地狱!
对于开头回调地狱的解决
function fn1() {
return new Promise((resolve, reject)=>{
setTimeout(()=>{
console.log('fn1...')
resolve()
}, 1000)
})
}
function fn2() {
return new Promise((resolve, reject)=>{
setTimeout(()=>{
console.log('fn2...')
resolve()
}, 1000)
})
}
function fn3() {
return new Promise((resolve, reject)=>{
setTimeout(()=>{
console.log('fn3...')
resolve()
}, 1000)
})
}
function onerror() {
console.log('error')
}
fn1().then(fn2).then(fn3).catch(onerror)
什么是 Promise
参考阮一峰 ES6教程。
Promise 是一个对象,对象里存储一个状态,这个状态是可以随着内部的执行转化的,为以下三种状态之一:等待态(Pending)、完成态(Fulfilled)、拒绝态(Rejected)。
一开始,我们先设置好等状态从 pending 变成 fulfilled 和 rejected 的预案(当成功后我们做什么,失败时我们做什么)。
Promise 启动之后,当满足成功的条件时我们让状态从 pending 变成 fullfilled (执行 resolve);当满足失败的条件,我们让状态从 pending 变成 rejected(执行 reject)
Promise 范例
范例1
Promise.prototype.then / Promise.prototype.catch
function getIp() {
var promise = new Promise(function(resolve, reject){
var xhr = new XMLHttpRequest()
xhr.open('GET', 'https://easy-mock.com/mock/5ac2f80c3d211137b3f2843a/promise/getIp', true)
xhr.onload = function(){
var retJson = JSON.parse(xhr.responseText) // {"ip":"58.100.211.137"}
resolve(retJson.ip)
}
xhr.onerror = function(){
reject('获取IP失败')
}
xhr.send()
})
return promise
}
function getCityFromIp(ip) {
var promise = new Promise(function(resolve, reject){
var xhr = new XMLHttpRequest()
xhr.open('GET', 'https://easy-mock.com/mock/5ac2f80c3d211137b3f2843a/promise/getCityFromIp?ip='+ip, true)
xhr.onload = function(){
var retJson = JSON.parse(xhr.responseText) // {"city": "hangzhou","ip": "23.45.12.34"}
resolve(retJson.city)
}
xhr.onerror = function(){
reject('获取city失败')
}
xhr.send()
})
return promise
}
function getWeatherFromCity(city) {
var promise = new Promise(function(resolve, reject){
var xhr = new XMLHttpRequest()
xhr.open('GET', 'https://easy-mock.com/mock/5ac2f80c3d211137b3f2843a/promise/getWeatherFromCity?city='+city, true)
xhr.onload = function(){
var retJson = JSON.parse(xhr.responseText) //{"weather": "晴天","city": "beijing"}
resolve(retJson)
}
xhr.onerror = function(){
reject('获取天气失败')
}
xhr.send()
})
return promise
}
getIp().then(function(ip){
return getCityFromIp(ip)
}).then(function(city){
return getWeatherFromCity(city)
}).then(function(data){
console.log(data)
}).catch(function(e){
console.log('出现了错误', e)
})
Promise.all
范例2
function getCityFromIp(ip) {
var promise = new Promise(function(resolve, reject){
var xhr = new XMLHttpRequest()
xhr.open('GET', 'https://easy-mock.com/mock/5ac2f80c3d211137b3f2843a/promise/getCityFromIp?ip='+ip, true)
xhr.onload = function(){
var retJson = JSON.parse(xhr.responseText) // {"city": "hangzhou","ip": "23.45.12.34"}
resolve(retJson)
}
xhr.onerror = function(){
reject('获取city失败')
}
xhr.send()
})
return promise
}
var p1 = getCityFromIp('10.10.10.1')
var p2 = getCityFromIp('10.10.10.2')
var p3 = getCityFromIp('10.10.10.3')
//Promise.all, 当所有的 Promise 对象都完成后再执行
详情,评价,购买人群
Promise.all([p1, p2, p3]).then(data=>{
console.log(data)
})
Pomise.all的使用
Promise.all可以将多个Promise实例包装成一个新的Promise实例。同时,成功和失败的返回值是不同的,成功的时候返回的是一个结果数组,而失败的时候则返回最先被reject失败状态的值。
let p1 = new Promise((resolve, reject) => {
resolve('成功了')
})
let p2 = new Promise((resolve, reject) => {
resolve('success')
})
let p3 = Promse.reject('失败')
Promise.all([p1, p2]).then((result) => {
console.log(result) //['成功了', 'success']
}).catch((error) => {
console.log(error)
})
Promise.all([p1,p3,p2]).then((result) => {
console.log(result)
}).catch((error) => {
console.log(error) // 失败了,打出 '失败'
})
Promse.all在处理多个异步处理时非常有用,比如说一个页面上需要等两个或多个ajax的数据回来以后才正常显示,在此之前只显示loading图标。
let wake = (time) => {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve(`${time / 1000}秒后醒来`)
}, time)
})
}
let p1 = wake(3000)
let p2 = wake(2000)
Promise.all([p1, p2]).then((result) => {
console.log(result) // [ '3秒后醒来', '2秒后醒来' ]
}).catch((error) => {
console.log(error)
})
需要特别注意的是,Promise.all获得的成功结果的数组里面的数据顺序和Promise.all接收到的数组顺序是一致的,即p1的结果在前,即便p1的结果获取的比p2要晚。这带来了一个绝大的好处:在前端开发请求数据的过程中,偶尔会遇到发送多个请求并根据请求顺序获取和使用数据的场景,使用Promise.all毫无疑问可以解决这个问题。
二、Promise.race的使用
顾名思义,Promse.race就是赛跑的意思,意思就是说,Promise.race([p1, p2, p3])里面哪个结果获得的快,就返回那个结果,不管结果本身是成功状态还是失败状态。
let p1 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('success')
},1000)
})
let p2 = new Promise((resolve, reject) => {
setTimeout(() => {
reject('failed')
}, 500)
})
Promise.race([p1, p2]).then((result) => {
console.log(result)
}).catch((error) => {
console.log(error) // 打开的是 'failed'
})
//Promise.all, 当所有的 Promise 对象都完成后再执行
Promise.race([p1, p2, p3]).then(data=>{
console.log(data)
})
---
# 使用脚手架搭建项目
## 安装
打开终端,切换到一个经常使用的项目目录,如
cd ~/projects
全局安装 vue-cli
npm install -g vue-cli
使用 vue-cli 创建 基于webpack模板的新项目
vue init webpack vue-evernote-client
![image](http://upload-images.jianshu.io/upload_images/3680331-2d24a6e125a00eb8.jpg?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
按回车![image](http://upload-images.jianshu.io/upload_images/3680331-f845ed9be840e3d3.jpg?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
按回车![image](http://upload-images.jianshu.io/upload_images/3680331-2acdffa3b4572408.jpg?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
按回车![image](http://upload-images.jianshu.io/upload_images/3680331-f4d15d222beab92e.jpg?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
使用默认选项 Runtime + Compile 即可,直接按回车![image](http://upload-images.jianshu.io/upload_images/3680331-9c03ebac148c260f.jpg?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
输入 Y,按回车![image](http://upload-images.jianshu.io/upload_images/3680331-808dcaf0fc96a4a8.jpg?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
输入 n,按回车![image](http://upload-images.jianshu.io/upload_images/3680331-09d68e206aa3280b.jpg?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
输入 n,按回车![image](http://upload-images.jianshu.io/upload_images/3680331-7ad18f8d05fa766b.jpg?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
输入 n,按回车![image](http://upload-images.jianshu.io/upload_images/3680331-3eb0aa018d1fe6e3.jpg?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
使用默认的 npm 作为包管理工具,直接按回车
等待安装,安装完毕后
进入当前项目目录
cd vue-evernote-client
安装依赖
npm install
![image](http://upload-images.jianshu.io/upload_images/3680331-b196241e84e1386a.jpg?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
启动server
npm run dev
浏览器打开 [http://localhost:8080](http://localhost:8080/ "null") ,即可看到搭建好的初始界面
![image](http://upload-images.jianshu.io/upload_images/3680331-9adbc38fedef364a.jpg-middle?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
可以使用编辑器打开 vue-evernote-client 这个目录,阅读代码,目前我们暂时只需要关注 src 这个目录即可。
|-- build // 项目构建(webpack)相关代码
| |-- build.js // 生产环境构建代码
| |-- check-version.js // 检查node、npm等版本
| |-- dev-client.js // 热重载相关
| |-- dev-server.js // 构建本地服务器
| |-- utils.js // 构建工具相关
| |-- webpack.base.conf.js // webpack基础配置
| |-- webpack.dev.conf.js // webpack开发环境配置
| |-- webpack.prod.conf.js // webpack生产环境配置
|-- config // 项目开发环境配置
| |-- dev.env.js // 开发环境变量
| |-- index.js // 项目一些配置变量
| |-- prod.env.js // 生产环境变量
| |-- test.env.js // 测试环境变量
|-- src // 源码目录
| |-- components // vue公共组件
| |-- apis // 请求接口
| |--utils // 工具库
| |-- views // 业务组件
| |-- store // vuex的状态管理
| |-- App.vue // 页面入口文件
| |-- main.js // 程序入口文件,加载各种公共组件
|-- static // 静态文件,比如一些图片,json数据等
| |-- data // 群聊分析得到的数据用于数据可视化
|-- .babelrc // ES6语法编译配置
|-- .editorconfig // 定义代码格式
|-- .gitignore // git上传需要忽略的文件格式
|-- README.md // 项目说明
|-- favicon.ico
|-- index.html // 入口页面
|-- package.json // 项目基本信息
![code.png](https://upload-images.jianshu.io/upload_images/3680331-d7fdfaa3f3497ce8.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)