关于javascript:Promise和AysncAwait的理解

37次阅读

共计 2627 个字符,预计需要花费 7 分钟才能阅读完成。

回调函数和 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 就呈现了。

// 对立执行 await
async function dbFuc(db) {let docs = [{}, {}, {}];
  let promises = docs.map((doc) => db.post(doc));

  let results = await Promise.all(promises);
  console.log(results);
}

// 批量执行 await
async 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 之后,能力执行后续的流程。

正文完
 0