回调函数和Promise

想要了解Promise和Aysnc(Aysnc、Await是搭配应用的,所以下文的Aysnc默认蕴含了Aysnc和Await关键字),首先要了解JavaScript中异步的概念。

// 传统写法let callback = function(value){    console.log(value)}let result = step1(function (value1) {  step2(value1, function(value2) {    step3(value2, function(value3) {      step4(value3, function(value4) {        //执行回调        callback(value4)      });    });  });});console.log(result)// Promise 的写法let result = (new Promise(step1)).then(step2).then(step3).then(step4);console.log(result)

在失常的逻辑下,是无奈实现异步的,为了实现异步,JavaScript中引入了回调函数(callback)的概念。也就是通过层层嵌套,最终的执行后果在回调函数中返回。

为了解决嵌套过多,解决代码不美观不易读的问题,Promise就呈现了。Promise想要解决的问题就是干掉回调函数,异步执行的代码能够写成同步执行的模式。

Promise必须和Aysnc、Await搭配应用

在应用Promise的中央必须应用Await进行标识,表明这是一个异步函数,必须期待Promise中的流程执行完结之后,能力执行前面的流程。

而Aysnc则应该写在标识有Await的外层函数上。

async function step1(value) {  let value1 = await step2(value);}

Aysnc和Await的用法就是这么简略,通知主函数这个函数是异步执行的,必须等它执行实现后能力进入到下一部流程。Aysnc和Await起到的是申明的作用,真正实现异步的逻辑其实是由Promise来承当的。

function step1(param) {    return new Promise(function(resolve, reject) {        //执行耗时的操作 比方mysql查问        mysql_query(sql, [param]).then((r) = >{            resolve(r)        }).catch(e = >{            reject(e)        })    }).then((r) = >{        console.log('resolve', r) return 'success result'    }).catch((e) = >{        console.log(e) return 'failed result'    });}

一个残缺的Promise对象由三局部组成:

  • 参数resolve, reject。这个局部能够使从内部传入的回调函数callback,也能够只是简略地标识。如果是简略地标识,那么正确执行之后resolve➡then,呈现谬误的的话reject➡catch。

  • then曾经不属于Promise的主体,而是程序执行的下一步。也就是说如果有必要,间接在Promise中传入参数,resolve之前return返回值,最终也可能收到后果。如果没有return,又有then的话,then的局部还会执行。

  • catch是链式写法的一部分,在Promise的主体中reject之后,就会执行catch这一部分。乏味的是Promise后紧跟的catch(链式写法),只管Promise的局部,甚至外部的抛出的异样它也没方法捕捉。所以mysql_query前面也写了catch,用于捕捉mysql_query本身谬误。否则mysql_query出错,会报unhandledpromiserejectionwarning异样。

Promise All的用法

你有没有留神到Promise办法外部并不是立刻执行返回的,而是新建并返回了一个Promise对象,这就是异步的精华。因为在写代码的时候,返回值什么时候可能取到(web申请什么时候胜利,SQL查问会不耗时太久等)咱们是无法控制的,咱们只能把获取后果的渠道建设后,最终的后果就会回到正规。

然而Promise针对的是单个工作,如果须要批量解决的业务,那么仅仅通过Promise就无奈解决。

async function someRequest() {    let result = true    for (let i = 0; i < 10; i++) {        result && await step1(i)    }    return result}

比方这样的一串异步申请,我试图通过多个异步申请的后果,判断最终有没有全副都执行胜利了。然而通过for循环执行时,第1个申请,第2,3,4...第n个申请之间是没有先后关系的,零碎不会等第1个执行完了,再程序执行第2,3,4...第n个,如果是这样也无奈体现出批量的意义。

而是同时收回n个申请,也就是同时new n个Promise,而后所有Promise同步执行。事实上还没等所有的await执行完结,for循环就遍历实现,而后return result了。

异步是指,后果的返回工夫、执行胜利与否咱们无法控制。同步是指咱们不关怀返回的后果是什么,而是立刻返回,在还没有从期待过程中取得后果的状况下,咱们就依照初始化的状况返回。

为了解决多个Promise异步的问题,Promise All就呈现了。

//对立执行awaitasync function dbFuc(db) {  let docs = [{}, {}, {}];  let promises = docs.map((doc) => db.post(doc));  let results = await Promise.all(promises);  console.log(results);}//批量执行awaitasync function dbFuc(db) {  let docs = [{}, {}, {}];  let promises = docs.map((doc) => db.post(doc));  let results = [];  for (let promise of promises) {    results.push(await promise);  }  console.log(results);}

对立执行和批量执行的后果都是一样的,目标保障所有Promise对象都执行实现后,拿到后果数组results之后,能力执行后续的流程。