## Promise 对象
> 1.Promise 的含义
2.基本用法
3.Promise.prototype.then()
4.Promise.prototype.catch()
5.Promise.prototype.finally()
6.Promise.all()
7.Promise.race()
### Promise的含义
同步和异步
在JavaScript的世界中,所有js代码都是单线程执行的,但是浏览器内部还有其他线程,比如浏览器事件,网络请求等都是其他线程在管理。而且这些操作都是相当耗时的。
如果这些也都是单线程的,那js在执行的时候,就不得不停下来等这些耗时的任务完成了才能继续向下执行。这会导致交互的延迟,体验极差。
为了解决这个问题了,我们将这些耗时的操作呢,处理成异步。就是如果触发请求,请求比较耗时,就先将耗时请求交给其他线程处理,js的主线程继续向下执行。等耗时的操作处理完毕后,通知js主线程执行回调。
![](https://box.kancloud.cn/bd5c223091a141728baf516d0dd53236_649x361.png)
~~~
$.ajax({
success:function(res){
var res = res
// 此处省略一万行代码
},
fail:function () {
}
})
~~~
~~~
asyncFunc1(opt, (...args1) => {
asyncFunc2(opt, (...args2) => {
asyncFunc3(opt, (...args3) => {
asyncFunc4(opt, (...args4) => {
// some operation
});
});
});
});
~~~
这就是所谓的回调地狱。回调嵌套导致了代码阅读性差,可复用性差。
我们希望这样的异步可以:
1.请求数据和处理数据能够分离开
2.代码可阅读性高
3.代码可复用性高
一般我们是采用如下的代码来处理
~~~
function cb(data) {
//处理data的n行代码
}
function errorcb(){
//处理请求失败的情况
}
function ajax(cb,errorcb) {
$.ajax({
success:function(data){
cb&&cb(data)
},
fail:function(){
errorcb&&errorcb()
}
})
}
ajax(cb,errorcb);
~~~
Promise写法,Promise集中管理异步请求的运行状态。回调函数处理正常或者异常操作。将ajax的请求状态逻辑和回调逻辑彻底分离开。
~~~
promise.then(function(value){
//成功的处理函数
},function(error){
//失败的处理函数
});
~~~
Promise 是异步编程的一种解决方案。除此之外还有Generator函数
ES6 将其写进了语言标准,统一了用法,原生提供了Promise对象。
Promise对象有以下两个特点
(1)对象的状态不受外界影响
(2)一旦状态改变,就不会再变,任何时候都可以得到这个结果
三种状态:
pending:进行中
fulfilled :已经成功
rejected 已经失败
状态改变:
Promise对象的状态改变,只有两种可能:
从pending变为fulfilled
从pending变为rejected。
这两种情况只要发生,状态就凝固了,不会再变了
### 基本用法
~~~
const promise = new Promise(function(resolve, reject) {
// ... some code
if (/* 异步操作成功 */){
resolve(value);
} else {
reject(error);
}
});
~~~
~~~
function timeout(ms) {
return new Promise((resolve, reject) => {
setTimeout(resolve, ms, 'done');
});
}
timeout(100).then((value) => {
console.log(value);
});
~~~
### Promise.prototype.then()
~~~
getJSON("/posts.json").then(function(json) {
return json.post;
}).then(function(post) {
// ...
});
~~~
可以连续调用then方法
~~~
getJSON("/post/1.json").then(function(post) {
return getJSON(post.commentURL);
}).then(function funcA(comments) {
console.log("resolved: ", comments);
}, function funcB(err){
console.log("rejected: ", err);
});
~~~
### Promise.prototype.catch()
~~~
getJSON('/posts.json').then(function(posts) {
// ...
}).catch(function(error) {
// 处理 getJSON 和 前一个回调函数运行时发生的错误
console.log('发生错误!', error);
});
~~~
### Promise.prototype.finally()
~~~
promise
.then(result => {···})
.catch(error => {···})
.finally(() => {···});
~~~
~~~
server.listen(port)
.then(function () {
// ...
})
.finally(server.stop);
~~~
### Promise.all()
~~~
const p = Promise.all([p1, p2, p3]);
~~~
~~~
// 生成一个Promise对象的数组
const promises = [2, 3, 5, 7, 11, 13].map(function (id) {
return getJSON('/post/' + id + ".json");
});
Promise.all(promises).then(function (posts) {
// ...
}).catch(function(reason){
// ...
});
~~~
### Promise.race()
~~~
const p = Promise.race([p1, p2, p3]);
const p = Promise.race([
fetch('/resource'),
new Promise(function (resolve, reject) {
setTimeout(() => reject(new Error('request timeout')), 5000)
})
]);
p
.then(console.log)
.catch(console.error);
~~~
上面代码中,只要p1、p2、p3之中有一个实例率先改变状态,p的状态就跟着改变。那个率先改变的 Promise 实例的返回值,就传递给p的回调函数。
### 课后习题
1.用promise实现一个函数,按顺序每隔一秒打印一个数字,范围是1-10。
- Less
- 课程规划
- Less概述
- 变量
- 混合
- 嵌套
- 继承
- 导入
- 函数
- 其他
- 实战
- ES6
- 课程规划
- ES6概述
- let和const命令
- 变量的解构赋值
- 字符串扩展
- 函数扩展
- 数组扩展
- Set和Map数据结构
- Symbol
- Generator 函数
- Promise对象
- Class语法
- Module 的语法
- ES7和ES8
- 实战
- VUE
- 课程规划
- vue概述
- vue实例
- 模版语法
- 计算属性和侦听器
- Class和Style的绑定
- 条件渲染
- 列表渲染
- 事件处理
- 表单输入绑定
- 组件基础
- 过渡和动画
- 自定义指令
- 过滤器
- 响应式原理
- 实战课程
- Node
- 课程规划
- 课程概述
- node入门实例
- 模块系统
- 回调函数
- 全局对象
- 常用模块介绍
- 常用模块介绍-1
- 常用模块介绍-2
- 常用模块介绍-3
- npm使用
- express的使用
- express的使用-1
- webpack基础
- 实战
- 微信小程序
- 课程规划
- 课程概述
- 基本配置和生命周期
- wxml模版
- wxss
- wxs
- 组件
- 微信API
- 自定义组件开发
- 实战小程序
- Element
- 课程规划
- 课程概述
- 特性介绍
- 组件介绍-基础组件
- 组件介绍-表单组件
- 组件介绍-数据展示组件
- 组件介绍-提示组件
- 组件介绍-导航组件
- 组件介绍-其他组件
- 综合案例