异步发展史,此次必定会!

啥叫异步?啥叫同步?🙉

同步:

每次只有一个线程其余线程被阻塞git

简单来讲,就是任务一个接着一个完成。只要一个没完成其余被堵塞github

异步:

不用阻塞当前线程来等待处理完成,而是容许后续操做,直至其它线程将处理完成,并回调通知此线程。编程

简单来讲,就是任务同时进行,中途可能须要等待其余任务完成才能进行当前任务。json

js为啥须要异步?🙉

js是单线程的,若是有一个任务咱们要花很长时间,那岂不是这以后的代码全被阻塞了。redux

Js的异步编程发展史👏

其实异步编程的发展的目的是愉快地coding:用同步写法写异步api

1. callback回调函数:

回调函数:异步操做执行完后触发执行的函数,相似以下格式:promise

$.get("http://xxx.xxxx.com/api",callback);
复制代码

优势:

  • 简单
  • 符合传统js

缺点:

  • 容易造成回调地狱 若是:咱们须要请求A接口获得学生id,经过学生id请求B接口获得学生成绩,再通学生成绩请求获得排名(不是很好的例子 但大概这个意思)
fetch({
    url: "/student",
    data:1,
    success: function (id) {
        fetch({
            url: "/score",
            data:id,
            success: function (score) {
                fetch({
                    url: "/rank",
                    data:score,
                    success: function (rank) {
                        console.log(rank)
                    }
                })
            }
        })
    }
})
复制代码
  • 回调嵌套会致使代码难以维护
  • 而且不方便统一处理错误(不能 try catch)

2. Promise:

Promise 必定程度上解决了回调地狱的问题,Promise 最先由社区提出和实现,ES6 将其写进了语言标准,统一了用法,原生提供了Promise对象。Promise对象简单说就是一个容器,里面保存着某个将来才会结束的事件(一般是一个异步操做)的结果。从语法上说,Promise 是一个对象,从它能够获取异步操做的消息。Promise 提供统一的 API,各类异步操做均可以用一样的方法进行处理。bash

fetch(1).then(id=> {
    return fetch(id);
}).then(score => {
    return fetch(score);
}).then(rank=> {
    console.log(rank)
}).catch(reason => {
    console.log(reason);
});
复制代码

优势:

  • 一旦状态改变,就不会再变,任什么时候候均可以获得这个结果
  • 能够将异步操做以同步操做的流程表达出来,避免了层层嵌套的回调函数

缺点:

  • 没法取消 Promise
  • 当处于pending状态时,没法得知目前进展到哪个阶段
  • 错误不能被 try catch

3. Generator

Generator 函数是 ES6 提供的一种异步编程解决方案,整个 Generator 函数就是一个封装的异步任务,或者说是异步任务的容器。异步操做须要暂停的地方,都用 yield 语句注明。 将函数分割出好多个部分,调用一次next就会继续向下执行。返回结果是一个迭代器,迭代器有一个next方法。多线程

function my_co (it) {
    return new Promise((resolve, reject) => {
        function next(data) {
            let {value, done} = it.next(data);
            if(!done) {
                value.then(val => {
                    next(val);
                }, reject);
            }else{
                resolve(value);
            }
            
        }
        next();
    });
}

function *getData() {
    let res=yield fetch('/student',()=>{});
    let res1=yield fetch('/score',res1,()=>{});
    let res2=yield fetch('/rank',res2,()=>{});
    return res2
}
let it=getData()
let id=it.next(it)
let score=it.next(id)
let rank=it.next(score)
my_co(getData()).then(data => {
    console.log(data);
});
复制代码

特别注意:
看上去彷佛咱们平常业务中generator的异步写法不经常使用,但实际上在某些库的开发中它有着重要用途。
对!说的就是那个redux-saga
并且仔细想一想还有那个异步编程的方式有这么大的控制性,想停就停!app

4. Aync await

async-await实际上是一个语法糖,它的实现就是将 Generator函数和自动执行器(co),包装在一个函数中。
async至关于用Promise.resolve()包裹其函数返回值。
await至关于generatorpromise的语法糖,至关于yield,但他以外的同步代码能够自动执行
🔔若是没有依赖性的话也能够用promise.all

//如上面那个例子
function fetchData(api) {
      let result
      let url = 'http://localhost:3000'
      fetch(url + api, {
        method: 'GET',
        headers: {
          'Content-Type': 'application/json',
        },
      })
        .then((res) => {
          return res.json()
        })
        .then((json) => {
          console.log(json)
          result=json
        })
       return result
}
async function getData(){
    let id=await fetchData('/student')
    let score=await fetchData('/score')
    let rank=await fetchData('/rank')
}
复制代码

优势:

  • 代码清晰,
  • 不用像 Promise 写不少 then ,
  • 能够处理回调地狱的问题
  • 而且错误能够被try catch
async function main() {
  try {
    const val1 = await firstStep();
    const val2 = await secondStep(val1);
    const val3 = await thirdStep(val1, val2);

    console.log('Final: ', val3);
  }
  catch (err) {
    console.error(err);
  }
}
复制代码

🌰试一试:

git 地址
内含关于四种方式异步编程的例子,欢迎你们试一试👀

附加

  1. js是怎么实现异步执行的?
    执行栈:
    执行栈能够看做是一个存储函数调用的栈结构,遵循先进后出。 执行js时就会往执行栈放入函数。遇到异步则被挂起放入任务队列。
    EventLoop:
    等执行栈空了,eventloop就会把要执行的代码从队列中放入执行栈。\
  2. WebWorker是真的多线程吗?详见【WebWorker,此次必定会!】
相关文章
相关标签/搜索