一. promise是什么
简单来说是一种异步流程的控制手段
-
所谓Promise ,简单说就是一个容器,里面保存着某个未来才会结束的事件(通常是一个异步操作)的结果。从语法上说,Promise是一个对象,从它可以获取异步操作的消息。Promise 对象的状态不受外界影响
-
在JavaScript的世界中,所有代码都是单线程执行的。 由于这个“缺陷”,导致JavaScript的所有网络操作,浏览器事件,都必须是异步执行。
异步执行容易造成回调地狱
例如:
$.ajax( success(){ $.ajax( success(){ } ) } ) 复制代码
使用promise的链式调用就可以很好的解决这个问题
例如:vue-resource
this.$http.post(url,parms).then(res => { console.log(res) },err => { }).then(res=>{ },err=>{ }) 复制代码
二.promise的使用及方法
ES6规定,Promise对象是一个构造函数,用来生成Promise实例。Promise本身有all、race、reject、resolve这几个方法
- Promise只有一个参数 叫excutor执行器,默认new时就会调用
let p = new Promise((resolve,reject)=>{ // 默认promise中的executor是同步执行的 resolve('买'); }); // then方法是异步调用的,事件环 p.then((value)=>{ // value成功的原因 console.log(value);//买 },(err)=>{ // err失败的原因 }); 复制代码
注意:then方法是Promise实例上的方法
-
Promise的reject、resolve方法
promise有三种状态:resolve 成功 reject 失败 pending 等待态。 如果一旦promise成功了就不能失败,相反也是一样的,只有状态是等待的状态时才可以转化状态。pending->reject(resolve)
1.Promise.resolve() 返回一个成功的promise
2.Promise.reject() 返回一个失败的promise
例:
let fs = require('fs'); // fileSystem function read(url) { return new Promise((resolve, reject) => { fs.readFile(url, 'utf8', function (err, data) { if (err) reject(err);//成功返回 resolve(data);//失败返回 }) }) } 复制代码
-
Promise的all、race方法
promise可以支持多个并发的请求,获取并发请求中的数据
1.Promise.all
这可能是个很有用的方法,它可以统一处理多个Promise。Promise.all能将多个Promise实例包装成一个Promse实例
let Promise1 = new Promise(function(resolve, reject){}) let Promise2 = new Promise(function(resolve, reject){}) let Promise3 = new Promise(function(resolve, reject){}) let p = Promise.all([Promise1, Promise2, Promise3]) p.then(funciton(){ // 三个都成功则成功 }, function(){ // 只要有失败,则失败 }) 复制代码
2.Promise.race()
与all方法类似,也可以将多个Promise实例包装成一个新的Promise实例 不同的是,all时大Promise的状态由多个小Promise共同决定,而race时由第一个转变状态的小Promise的状态决定,第一个是成功态,则转成功态,第一个失败态,则转失败态。
** 简单来说就是赛跑,处理多请求只取最快的 **
let fs = require('fs'); // fileSystem function read(url) { return new Promise((resolve, reject) => { fs.readFile(url, 'utf8', function (err, data) { if (err) reject(err);//成功返回 resolve(data);//失败返回 }) }) } Promise.race([read('1.txt'),read('2.txt')]).then((data)=>{ console.log(data);//最快读取完成功则成功 },err=>{ console.log(err);//最快读取完失败则失败 }); 复制代码
三. promise的简单实现
通过上文我们已经知道Promise是一个构造函数,我们可以使用ES6的class类来创建一个Promise
下面我们创建一个class类来完成promise的then、reject、resolve方法
class Promise {
constructor(executor) {
// 默认状态是等待态
this.status = 'pending';
this.value = undefined;
this.reason = undefined;
// 存放成功的回调
this.onResolvedCallbacks = [];
// 存放失败的回调
this.onRejectedCallbacks = [];
let resolve = (data) => {
if (this.status === 'pending') {
this.value = data;
this.status = 'resolved';
this.onResolvedCallbacks.forEach(fn => fn());
}
}
let reject = (reason) => {
if (this.status === 'pending') {
this.reason = reason;
this.status = 'rejected';
this.onRejectedCallbacks.forEach(fn => fn());
}
}
try { // 执行时可能会发生异常
executor(resolve, reject);
} catch (e) {
reject(e); // promise失败了
}
}
then(onFulFilled, onRejected) {
if (this.status === 'resolved') {
onFulFilled(this.value);
}
if (this.status === 'rejected') {
onRejected(this.reason);
}
// 当前既没有完成 也没有失败
if (this.status === 'pending') {
// 存放成功的回调
this.onResolvedCallbacks.push(() => {
onFulFilled(this.value);
});
// 存放失败的回调
this.onRejectedCallbacks.push(() => {
onRejected(this.reason);
});
}
}
}
module.exports = Promise;
复制代码
完成了基本的功能,我们可以使用自己写的promise来测试一下
let Promise = require('./promise');//引入
let p = new Promise((resolve,reject)=>{
resolve(123);
reject(123);
});
p.then((data)=>{
console.log('s',data);//s,123
},(err)=>{
console.log('e',err);//e,123
});
复制代码
总结:
-
Promise是一种异步流程的控制手段
-
每一个promise的实例上都有一个then方法,then方法中有两个参数,一个参数叫成功的函数 ,一个是失败的函数
-
Promise可以链式调用,并且可以支持多个并发的请求,获取并发请求中的数据
-
如果一旦promise成功了就不能失败,相反也是一样的。只有状态是等待的状态时 才可以转化状态
-
Promise可以解决异步的问题,但不能说promise本身是异步的