JS 异步编程

305 阅读2分钟
并发是宏观概念,我分别有任务 A 和任务 B,在一段时间内通过任务间的切换完成了这两个任务,这种情况就可以称之为并发。

并行是微观概念,假设 CPU 中存在两个核心,那么我就可以同时完成任务 A、B。同时完成多个任务的情况就可以称之为并行。

回调地狱的根本问题就是:
嵌套函数存在耦合性,一旦有所改动,就会牵一发而动全身
嵌套函数一多,就很难处理错误

function *foo(x) {
  let y = 2 * (yield (x + 1))
  let z = yield (y / 3)
  return (x + y + z)
}
let it = foo(5)
console.log(it.next())//next()第一次调用,返回第一个yield后面的值
VM229:7 {value: 6, done: false} 
it.next(12)//next()第二次调用,入参赋值给第一个yield后面的值,返回当前yield后面的值
{value: 8, done: false}  
it.next(13)//入参赋值给上一个yield后面的值,返回函数return值
{value: 42, done: true}

解析:z=13 x=5  y=24

Promise:承诺会在未来有一个确切的答复,一旦从等待状态变成为其他状态就永远不能更改状态

当我们在构造 Promise 的时候,构造函数内部的代码是立即执行的

new Promise((resolve, reject) => {
  console.log('new Promise')
  resolve('success')
})
console.log('finifsh')
// new Promise -> finifsh

Promise 缺点:比如无法取消 Promise,错误需要通过回调函数捕获。

async 及 await

一个函数如果加上 async ,那么该函数就会返回一个 Promise

async function test() {
  return "1"
}
console.log(test()) // -> Promise {<resolved>: "1"}

async 就是将函数返回值使用 Promise.resolve() 包裹了下

相比 Promise 来说,优势:处理 then 的调用链,优雅地解决回调地狱问题。

缺点,因为 await 将异步代码改造成了同步代码,如果多个异步代码没有依赖性却使用了 await 会导致性能上的降低。

async function test() {
  // 以下代码没有依赖性的话,完全可以使用 Promise.all 的方式
  // 如果有依赖性的话,其实就是解决回调地狱的例子了
  await fetch(url)
  await fetch(url1)
  await fetch(url2)
}