随便说说Promise
为啥要说 promise ?
因为这是前端必须要掌握的一个知识,吹逼必备
首先说说 Promise 是什么?
Promise 是JavaScript的第一个异步标准模型,一个包含传递信息与状态的对象,emmm...它的英语意思是承诺.
so 它拥有的特点也有承诺的意思(兄弟们,拿好笔记本,划重点):
- 对象的状态不受外界影响,Promise 表示一个异步的操作,它有三个状态 Pending (进行时)、Reslove (已完成)、Rejected (失败),只有异步操作的结果,可以决定当前是哪一种状态
- 一旦状态改变就不会再接受改变,任何时候都可以得到这个结果。 Promise 对象的状态改变,只有两种可能,从 Pending 变为 Resolved 或者 Rejected。 只要这两种情况发生,状态就不会再改变了,就算状态改变了,你再对 Promise 对象添加回调,也会立即得到结果,这和事件 event 不同,事件的特点是一点你错过了它,再去监听也不会得到结果的
那 Promise 为什么会出现呢?
Promise 之前的异步
Promise之前的时候,我们用三个手段解决异步问题
- 回调函数
- 观察者模式(又称发布订阅模式)
- 事件机制
回调函数是最简单的异步方式,它比较容易理解和部署,也是我们最常使用的,但是缺点也很明显,不利于代码的阅读和维护,流程混乱。
观察者模式和事件机制不多说,就是适用于多次同类型的异步,不适用一次性的异步
而 Promise 可以将异步操作以同步操作的流程表达出来,
- 避免了层层回调函数。
- 如果使用回调函数, 你并不能知道对方是否执行你的回调函数,或太晚太早执行
- 错误也是异步,会隐式传递给reject
老哥,说了这么多,怎么用啊?
先来个最简单的Prmise
const p = new Promise((resolve,reject)=>{
setTimeout(()=>{
resolve('你好,兄弟') //设置成resolve状态 即是成功
},1e3)
})
p.then(res=>{
console.log(res) // 1s后输出 ==> 你好,兄弟
})
是不是看起来 so easy ?
下面我们来实现一下最简单的 Promise。 Promise只是一个普通的构造函数,用es3的语法也可以实现
所以在ie6都可以用,不过我们就使用class来实现了
class myPromise {
constructor(fn) {
this.state = 'PENDING';
this.message = '';
this.fns = [];
fn(this.resolve.bind(this), this.reject.bind(this));
}
resolve(res) {
this.state = 'FULFILLED';
this.message = res;
this._onChange();
}
reject(err) {
this.state = 'REJECTED';
this.message = err;
this._onChange();
}
then(onResolved, onRejected) {
let self = this;
return new myPromise((resolve, reject) => {
self.fns.push([onResolved, onRejected, resolve, reject]);
self._onChange();
});
}
_onChange() {
this.state !== 'PENDING' &&
this.fns.forEach(v => {
this._change(v);
});
}
_change(arr) {
let onResolved = arr[0],
onRejected = arr[1],
resolve = arr[2],
reject = arr[3];
switch (this.state) {
case 'FULFILLED':
if (typeof onResolved === 'function') {
resolve(onResolved.call(null, this.message));
} else {
resolve(this.message);
}
break;
case 'REJECTED':
if (typeof onRejected === 'function') {
resolve(onRejected.call(null, this.message));
} else {
reject(this.message);
}
break;
default:
break;
}
}
}
//老哥们注意,这只是我自己写的一个简略的 Promise , 并不是真正的 Promise 的实现
const p = new myPromise((resolve, reject) => {
setTimeout(() => {
resolve('你好,兄弟'); //1s后设置成resolve状态 即是成功
}, 1e3);
});
p.then(res => {
console.log(res); // 1s后输出 ==> 你好,兄弟
return '1';
})
.then(res => {
console.log(res); // 1s后输出 ==> '1'
})
.then(res => {
console.log(res); // 1s后输出 ==> undefined
});
Promise.resolve / reject
Promise 还提供一个快速实例化 Promise ,可以传入参数并且马上触发 Promise 链的执行
Promise.resolve = data =>
new Promise((resolve, reject) => {
resolve(data);
});
Promise.reject = err =>
new Promise((resolve, reject) => {
reject(err);
});
Promise.all / race
Promise 还提供 all / race 用来处理数据的并发和竞争,要求是传一个 Promise 数组作为参数,然后返回一个新的 Promise
all 是全部处理后再统一处理
Promise.all = arr =>
new Promise((resolve, reject) => {
let c = 0,
l = arr.length,
result = [];
l === 0 && resolve(result);
arr.forEach(pro => {
Promise.resolve(pro).then(res => {
result.push(res);
c++;
c === l && resolve(result);
},
err => {
reject(err);
}
);
});
});
race 则是谁异步时间短谁就会被处理
Promise.race = arr =>
new Promise((resolve, reject) => {
arr.forEach(pro => {
Promise.resolve(pro).then(resolve, reject);
});
});
Promise.then / catch
Promise 的 then 函数我们也知道是怎么用的,它始终以当前的结果返回一个新的Promise
而之前我们说到 Promise 的错误是异步的 也直接调用到 reject,
那我们在 resolve 或者 reject 出现错误应该怎么做呢? Promise 还提供一个catch 用来捕捉错误
Promise.catch = reject => this.then(undefined,reject)
怎么用呢?
const p = new Promise((resolve, reject) => {
//执行操作
//..略
});
p.then(resolve, reject)
.then(resolve, reject)
.then(resolve, reject)
.catch(err => {
//如果以上出现错误会直接传递到此处执行错误处理
});
Promise 和 setTimeout
说是异步,那么和我们最原始的 setTimeout 有什么区别呢?
先让我们看一道面试题目
console.log('a');
setTimeout(() => {
console.log('b');
});
console.log('c');
new Promise((resolve, reject) => {
console.log('d');
resolve('e');
}).then(res => {
console.log(res);
});
console.log('f');
输出顺序是什么呢 ?
a => c => d => f => e => b
这里就要关系到js的 EventLoop 机制了,这里并不细说,只是抛个引子,有兴趣的朋友可以去看看相关文章
结尾
到这里就结束了,老哥们,要去搬砖了
如果发现文章有什么问题,可以留言哦
随便说说Promise的更多相关文章
- 大白话讲解Promise(三)搞懂jquery中的Promise
前两篇我们讲了ES6中的Promise以及Promise/A+规范,在Promise的知识体系中,jquery当然是必不可少的一环,所以本篇就来讲讲jquery中的Promise,也就是我们所知道的D ...
- 大白话讲解Promise(一)
去年6月份, ES2015正式发布(也就是ES6,ES6是它的乳名),其中Promise被列为正式规范.作为ES6中最重要的特性之一,我们有必要掌握并理解透彻.本文将由浅到深,讲解Promise的基本 ...
- Promise学习
转自:http://www.cnblogs.com/lvdabao/p/es6-promise-1.html 去年6月份, ES2015正式发布(也就是ES6,ES6是它的乳名),其中Promise被 ...
- 你不知道的JavaScript--大白话讲解Promise
转载:http://blog.csdn.net/i10630226/article/details/50867792 一.Promise小试 复杂的概念先不讲,我们先简单粗暴地把Promise用一下, ...
- 你是否也在学习ES6 Promise时遇到过这个问题?
背景 周末闲来无事,随便翻看了一下阮一峰老师的<ES6 标准入门>第2版,ps:之前在阮一峰老师的官网看过电子版,感觉干货满满,所以就买了纸质版:当看到第16章第4节 'Promise.p ...
- Promise小书(长文)
promise基础 Promise是异步编程的一种解决方案.ES6 Promise的规范来源于Promises/A+社区,它有很多版本的实现. Promise比传统的解决方案(回调函数和事件)更合理和 ...
- Es6 Promise 用法详解
Promise是什么?? 打印出来看看 console.dir(Promise) 这么一看就明白了,Promise是一个构造函数,自己身上有all.reject.resolve这几个眼熟的方 ...
- angularjs promise详解
一.什么是Promise Promise是对象,代表了一个函数最终可能的返回值或抛出的异常,就是用来异步处理值的. Promise是一个构造函数,自己身上有all.reject.resolve这几个异 ...
- 聊一聊promise的前世今生
promise的概念已经出现很久了,浏览器.nodejs都已经全部实现promise了.现在来聊,是不是有点过时了? 确实,如果不扯淡,这篇随笔根本不会有太多内容.所以,我就尽可能的,多扯一扯,聊一聊 ...
随机推荐
- 在Android源码中如何吧so库打包编译进入apk, 集成第三方库(jar和so库)
集成第三方so和jar包 include $(CLEAR_VARS) #jar包编译 LOCAL_PREBUILT_STATIC_JAVA_LIBRARIES :=securit ...
- C# ObjectArx cad二次开发
1 环境搭建:安装CAD 和objectArx库,这里安装的是cad2012和objectArx2010 ,vs是2010 2 新建一个类库项目,引用objectArx安装目录下inc文件夹下的AcD ...
- OLEDB 调用存储过程
除了常规调用sql语句和进行简单的插入删除操作外,OLEDB还提供了调用存储过程的功能,存储过程就好像是用SQL语句写成的一个函数,可以有参数,有返回值. 存储过程除了像普通函数那样返回一般的值以外, ...
- CMDB认识和需求分析
一.认识ITIL ITIL即IT基础架构库(Information Technology Infrastructure Library,信息技术基础架构库)由英国政府部门CCTA(Central ...
- 从零开始的全栈工程师——jQuery
jQueryjq是js一个高效且精简的库( 用的多写得少 ) ,是chrome出版的.jq内部有一个$的方法,他是jq的起始符或标识符,这个方法是用于获取元素. 下载库或者框架的方法官网 produc ...
- 【数据库】6.0 MySQL入门学习(六)——MySQL启动与停止、官方手册、文档查询
1.0 MySQL主要有四种启动方式:直接启动.安全启动.服务启动.多实例启动. 直接启动: 服务器启动: 安全启动(最常用): 多实例启动: 2.0如何获得MySQL帮助 2.1官方手册 下面提供百 ...
- 初入门 HTML
---恢复内容开始--- 1.h标签(标题标签) h1~h62.br标签(换行标签) <br/>3.hr标签(水平线标签) <hr/>4.strong(加粗) em(倾斜)5. ...
- 使用jquery去掉时光轴头尾部的线条
一.前言:以前做类似时光轴的结构,几乎都是一条灰色线飞流直下,没有尽头.今天这个线条是从第一个圆点到最后一个圆点,那么问题来了,内容的高度还不是固定的,线条的长度怎么确定?怎么就能刚刚好从第一个点到最 ...
- python 继承式多线程
Thread是线程类,有两种使用方法,直接传入要运行的方法或从Thread继承并覆盖run(): Thread继承 import threading import time class MyThrea ...
- C/C++:函数的调用约定(Calling Convention)和名称修饰(Decorated Name)以及两者不匹配引起的问题
转自:http://blog.csdn.net/zskof/article/details/3475182 注:C++有着与C不同的名称修饰,主要是为了解决重载(overload):调用约定则影响函数 ...