promise是什么
官网诠释 promise 示意一个异步操纵的终究效果。
翻译 ==能够将promise理解为一个状况机==,它存在三种差别的状况,并在某一时刻只能有一种状况
- pending 示意还在实行
- resolved 实行胜利
- rejected 实行失利
一个promise是对一个异步操纵的封装,异步操纵有守候完成、胜利和失利三种能够的效果,对应了promise的三种状况。
promise的状况只能有pending转换位resolved或许pending转换为rejected,一旦状况转化完造诣没法再转变。
假定我们用promise封了一个异步操纵,那末当它被建立的时刻就处于pending状况,当异步操纵胜利完成时,
我们将状况转换为resolved,假如实行中涌现毛病,将状况转换为rejected。
var promise=new Promise(function(resolve,reject){
// code
if(){
/*异步操纵胜利 */
resolve(value)
}else{
reject(error)
}
})
运用then要领猎取效果
var fs=require('fs')
function readFile_promise(path){
return new Promise(function(resolve,reject){
fs.readFile(path, 'utf-8',function(err,data){
if(data){
resolve(data)
}else{
reject(err)
}
})
})
}
var result=readFile_promise('./1.txt')
result.then(function(value){
//success
console.log('success', value)
},function(error){
//failure
console.log('failure',error)
})
// 将一个异步函数封装成promise,只要在回调函数中针对差别的返回效果挪用resolve或许reject要领。
// resolve函数会在异步操纵胜利完成时被挪用,并将异步操纵的返回值作为参数通报到外部。
// reject是在异步操纵涌现异常时被挪用,会将毛病信息作为参数通报出去。
then要领的返回值
then要领老是返回一个新的promise对象,屡次挪用then要领,默许返回一个一个空的promise对象
运用return来来返回。
var promise=readFile_promise('./foo.txt')
promise.then(function(value){
//success
console.log('success', value) // foo
return readFile_promise('./bar.txt')
},function(error){
//failure
console.log('failure',error)
}).then(function(value){
console.log('then', value) // bar
})
promise的实行
- 虽然我们是经由历程then要领来猎取promise的效果,然则promise是当then要领挪用以后才实行吗?
var promise=new Promise((resolve, reject)=>{
console.log('begin')
resolve()
})
setTimeout(()=>{
promise.then(()=>{
console.log('end')
})
},5000)
// 最先begin 5s后end
// 运转递次是,当promise从被建立的那一刻起就最先实行了,then要领只是供应了接见promise状况的接口,与promise的实行无关。
promise 经常使用的api
- resolved
- rejected
- all
- race 要领吸收一个promise数组作为参数并返回一个新的promise,数组中的promise会同时最先实行,race返回的promise的状况有数组中领先实行终了的promise的状况决议
- catch 实行失足能够运用throw症结字抛出毛病,并运用catch要领举行捕捉
// 假如有多个promise须要实行,能够运用promise.all()
// 要领一致声明,改要领能够将多个promise对象包装成一个promise
// 该要领吸收一个数组作为参数,数据的元素假如不是promise对象,则回先挪用resolve要领转换。
// 假如中心有一个promise状况是reject,那末转换后的promise也会变成reject,而且将毛病信息传给catch要领
var promises=['foo.txt','bar.txt','baz.txt']
promises.map(function(path){
// console.log(path)
return readFile_promise(path)
})
Promise.all(promises).then(function(results){
console.log(results) // [ 'foo.txt', 'bar.txt', 'baz.txt' ] 递次排列的
}).catch(function(err){
//
})
运用promise构造异步代码
// 例子; 有三个文本文件须要递次读取
var lists=['foo.txt','bar.txt','baz.txt']
var count=0;
readFile_promise('foo.txt').then(readCB).then(readCB).then(readCB);
function readCB(data){
console.log(data) // foo bar baz
if(++count>2){
return
}
return readFile_promise(lists[count])
}
async/await
await症结字背面往往是一个promise,假如不是就隐式挪用promise.resolve来转换成一个promise。
await 守候背面的promise实行完成再举行下一步操纵。
var asyncReadFile=async function(){
var result1=await readFile_promise('./foo.txt')
console.log(result1.toString()) // foo
}
asyncReadFile()
async返回值
async函数老是会返回一个promise对象,假如return症结字背面不是一个promise,那末默许
挪用promise。resolve要领举行转换。
async function asyncFunc(){
return 'hello Node'
}
asyncFunc().then(function(data){
console.log(data) // hello Node
})
async函数的实行历程
- 在async函数最先实行的时刻回自动天生一个promise对象。
- 当要领体最先实行后,假如碰到return症结字或许throw症结字,实行会马上退出,
假如碰到await症结字则回停息实行 await背面的异步操纵完毕后会恢复实行
- 实行终了,返回一个promise
async function asyncFunc(){
console.log('begin')
return 'hello Node'
}
asyncFunc().then(function(data){
console.log(data) // hello Node
console.log('end')
})
// begin
// hello
// end
await
await 操纵符的效果是由其背面promise对象的操纵效果来决议的,假如背面promise对象变成resolved,
await操纵符发返回的值就是resolve的值;假如promise对象的状况变成rejected,那末await也会抛出reject的值。
async function readFile(){
var result=await readFile_promise('./foo.txt')
console.log(result) // foo
}
readFile()
// 等价于
readFile_promise('foo.txt').then(function(data){
console.log(data) // foo
})
await于并行
await会守候背面的promise完成后再采用下一步行动,这意味着当多个await操纵时,顺序会便成完整的
串行操纵。
当异步操纵之间不存在依靠关联时,能够运用promise.all来完成并行。
async function readFile(){
const [result1, result2]=await Promise.all([
readFile_promise('./foo.txt'),
readFile_promise('./bar.txt')
])
console.log(result1, result2) // foo bar
}
readFile()
// 等价于
function readFile(){
return Promise.all([
readFile_promise('./foo.txt'),
readFile_promise('./baz.txt')
]).then((result)=>{
console.log(result) // [ 'foo', 'baz' ]
})
}
readFile()
await 总结
await症结字运用的一些症结点
- await症结字必需位于async函数内部
- await症结字背面须如果一个promise对象(不是的话就挪用了resolve转换的)
- await症结字的返回效果就是在其背面promise实行的效果,多是resolved或许rejected的值
- 不能在一般箭头函数中运用await症结字,须要在箭头函数前面加上async症结字。
- await用来串行地实行异步操纵,想完成并行运用promise.all
async函数 的瑕玷
- 假定我们有很多层的要领挪用,最底层的异步操纵被封装成了async要领,那末该函数的一切上层要领能够都要变成async要领。