如许明白 promise

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函数的实行历程
  1. 在async函数最先实行的时刻回自动天生一个promise对象。
  2. 当要领体最先实行后,假如碰到return症结字或许throw症结字,实行会马上退出,

假如碰到await症结字则回停息实行 await背面的异步操纵完毕后会恢复实行

  1. 实行终了,返回一个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要领。
    原文作者:甜土豆
    原文地址: https://segmentfault.com/a/1190000018625195
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞