简单的说它是一个异步流程的控制手段。是一个表明了异步操做最终完成或者失败的对象。php
在传统的ajax调用过程当中,下面以jquery.ajax为例。若是需求中要屡次进行ajax交互,而且上一次的返回结果还要被下一次的ajax使用,代码基本上会变成:jquery
$.ajax({
type: "POST",
url: "some.php",
data: "name=John&location=Boston",
success: function(msg){
$.ajax({
type: "POST",
url: "some.php",
data: msg,
success: function(msg2){
...//屡次调用
}
});
}
});
复制代码
如今还只是两次调用关系,若是是屡次调用将会引起下面的问题ajax
promise的链式调用就很好的解决了这个问题数组
promise 中的状态只能是从等待状态转换到成功状态或者失败状态,且状态转变以后不可逆。promise
let p = new Promise((resolve, reject) => {
console.log(1)
});
console.log(2)
//1 2
复制代码
promise里面只接受一个参数,叫作执行器函数,这个函数会同步执行。也就是说上面代码中的箭头函数被同步执行,获得的结果也就是1和2并发
每个promise的实例上都有一个then方法,这个方法上有两个参数,一个是成功的回调,一个是失败的回调。而取决于成功或者失败的是promise的执行器函数中执行的是成功仍是失败。异步
let p = new Promise((resolve, reject) => {
console.log(1);
resolve();//调用resolve会走到then的成功回调
//reject();//调用resolve会走到then的失败回调
});
p.then(
() => {
console.log('成功')
}
, () => {
console.log('失败')
})
//1 成功
复制代码
若是既不调用resolve也不调用reject,promise则一直处于等待状态,也就不会走到then方法。函数
let p = new Promise((resolve, reject) => {
console.log(1);
});
p.then(
() => {
console.log('成功')
}
, () => {
console.log('失败')
})
//1
复制代码
若是你既调用resolve也调用reject,那么谁在前面执行就走谁的对应回调函数post
let p = new Promise((resolve, reject) => {
console.log(1);
resolve()//先调用成功
reject()
});
p.then(
() => {
console.log('成功')
}
, () => {
console.log('失败')
})
//1 成功
复制代码
let p = new Promise((resolve, reject) => {
console.log(1);
reject()//先调用失败
resolve()
});
p.then(
() => {
console.log('成功')
}
, () => {
console.log('失败')
})
//1 失败
复制代码
若是代码出错则会直接走reject的回调ui
let p = new Promise((resolve, reject) => {
console.log(1);
throw new Error('出错了~')
});
p.then(
() => {
console.log('成功')
}
, () => {
console.log('失败')
})
//1 失败
复制代码
一个promise的实例能够then屡次
let p = new Promise((resolve, reject) => {
resolve('成功了');
});
p.then((data) => {
console.log(data)//成功了
});
p.then((data) => {
console.log(data)//成功了
})
复制代码
可以规避异步操做中回调地狱的问题,其本质取决于promise的链式调用。 假设需求以下,a.txt文件的内容为b.txt,b.txt文件的内容是一段描述文字,如今要求用a.txt的获得最终的描述文字,代码以下:
let fs = require('fs');
//首先将异步方法封装在一个promise中,异步结果成功调用resolve方法,失败调用reject方法。
function read(url) {
return new Promise((resolve, reject) => {
fs.readFile(url, 'utf8', function (err, data) {
if (err) reject();
resolve(data);
})
})
}
//由于read方法返回的是一个promise,因此可使用promise的then方法
read('a.txt').then((data) => {
//第一次异步成功后拿到结果继续返回一个promise能够实现链式调用。
console.log(data);//b.txt
return read(data);
}, (err) => { }).then((data) => {
//最后两次的结果分别对应两次异步的返回内容
console.log(data)//描述文字
}, (err) => { })
复制代码
总结:若是一个promise的then方法中还返回另外一个promise,那么这个promise的成功状态会走到外层promise的下一次then方法的成功,若是失败,返回外层promise下一次then的失败。
read().then((data) => {
return 111
}, (err) => { }).then((data) => {
console.log(data)//111
}, (err) => { })
复制代码
read().then((data) => {
throw new Error('出错了~')
}, (err) => { }).then((data) => {
console.log(data)
}, (err) => {
console.log(err)//出错了~
})
复制代码
read().then((data) => {
cons.log(111)
}, (err) => { }).then((data) => {
console.log(data)//undefined
}, (err) => {
})
复制代码
read().then((data) => {
throw new Error('出错了~')
}, (err) => { }).then((data) => {}, (err) => {}).catch((err)=>{
//错误处理
})
复制代码
read().then((data) => {
throw new Error('出错了~')
}, (err) => { }).then((data) => {}, (err) => {}).catch((err)=>{
//错误处理
}).then((data) => {}, (err) => {})
复制代码
all方法能够处理多个请求并发的问题。参数是一个数组。all方法调用后会返回一个新的promise。
let fs = require('fs');
function read(url) {
return new Promise((resolve, reject) => {
fs.readFile(url, 'utf8', function (err, data) {
if (err) reject();
resolve(data);
})
})
}
Promise.all([read('1.txt'), read('2.txt')]).then((data) => {
console.log(data)//[ '文本1内容', '文本2内容' ]
}, (err) => {
console.log(err);
})
复制代码
在all方法中一个失败了就所有失败,因此都成功了才会走成功回调。
Promise.all([read('1.txt'), read('3.txt')]).then((data) => {
console.log(data)
}, (err) => {
console.log('失败了');//失败了
})
复制代码
多个请求中,谁的返回数据最快,结果就是谁
Promise.race([read('1.txt'), read('2.txt')]).then((data) => {
console.log(data)////文本2内容
}, (err) => {
console.log('失败了');
})
复制代码
返回一个成功的Promise
Promise.resolve('123').then((data) => {
console.log(data)//123
})
复制代码
返回一个失败的Promise
Promise.reject('123').then((data) => {
console.log('err', data)//err 123
})
复制代码
若是你想手写一个promise,请戳下面的连接: 手写promise