• 【JavaScript】异步JavaScript


    什么是异步

    在JavaScript中,程序的执行是顺序的,是单线程的,即一次只能做一件事情

    比如:页面在加载图片或进行大量运算时,用户将无法进行其它操作

    这个时候控制权并没有在用户手上,整个浏览器就像冻结一样,这叫做阻塞

    异步就是为了能够解决这类问题而出现的

    异步实现

    1. 异步callbacks(旧)

    1.1 基本用法

    异步callbacks就是函数,且该函数作为参数传递给其它在后台执行的函数;

    当后台运行结束,就通过调用callbacks函数,通知你工作已经完成(捕获到事件)

    如:addEventListener()第二个参数

    当监听到click事件的时候,就会调用回调函数(callback)

    btn.addEventListener('click', () => {
      alert('You clicked me!');
    
      let pElem = document.createElement('p');
      pElem.textContent = 'This is a newly-added paragraph.';
      document.body.appendChild(pElem);
    });

     1.2 回调地狱

    下面这个例子来自MDN官方文档

    “ 我们来谈谈订购披萨作为类比。为了使你的订单成功,你必须按顺序执行,不按顺序执行或上一步没完成就执行下一步是不会成功的:

    1. 选择配料。如果你是优柔寡断,这可能需要一段时间,如果你无法下定决心或者决定换咖喱,可能会失败。
    2. 下订单。返回比萨饼可能需要一段时间,如果餐厅没有烹饪所需的配料,可能会失败。
    3. 然后你收集你的披萨吃。如果你忘记了自己的钱包,那么这可能会失败,所以无法支付比萨饼的费用!“
    chooseToppings(function(toppings) {
      placeOrder(toppings, function(order) {
        collectOrder(order, function(pizza) {
          eatPizza(pizza);
        }, failureCallback);
      }, failureCallback);
    }, failureCallback);
    

    对于每个回调函数都需要有一个failureCallback(),使得代码十分冗余

    2. Promises(新)

    2.1 基本用法

    使用fetch来获取事件

    then用来包含要执行的回调操作,且每个回调都接收前一个成功操作的结果作为输入,可对传过来的结果继续进行操作

    catch用于捕获所有then中的错误

    fetch('products.json').then(function(response) {
      return response.json();
    }).then(function(json) {
      products = json;
      initialize();
    }).catch(function(err) {
      console.log('Fetch problem: ' + err.message);
    });
    

    2.2 Promise术语

    1.创建promise时,其所处状态为pending(待定)

    2.当promise返回时,称为resolved(已解决)

      2.1 一个成功resolved的promise称为fullfilled(实现)。它返回一个值,可以通过.then()块链接到promise链的末尾来访问该值。.then()块中的执行程序函数将包含promise的返回值。

      2.2一个未能resolved的promise称为rejected(拒绝)。它返回一个原因(reason),一条说明为什么拒绝的错误消息。可以通过将.catch()块链接到promise链的末尾来访问此原因。

    2.3 Promise fullfill/reject后运行一些最终代码

    将.finally()方法链接到promise链的末尾即可

    myPromise
    .then(response => {
      doSomething(response);
    })
    .catch(e => {
      returnError(e);
    })
    .finally(() => {
      runFinalCode();
    });
    

      

    3. async和await

    3.1 基本用法

    将async关键字放在函数声明前,使其称为async function(异步函数)

    如下,hello将返回一个promise对象

    async function hello() { return "Hello" };
    hello();

    由上一小节2.Promises可知,可以使用.then()块进行后续操作

    hello().then((value) => console.log(value))
    

    await关键字只在异步函数里面才起作用

    重写2.Promises中代码

    async function myFetch(){
        let response = await fetch('products.json');
        let products = await response.json;
        initialize();
    }
    
    myFetch()
    .catch(err=>{
        console.log('Fetch problem: ' + err.message);
    })
    

    可以看到通过关键字可以除去.then()代码块,代码更加简单易懂

    3.2 代码时如何工作的?

    Javascript运行到await时将暂停,并允许其它代码在此期间执行,直到异步函数调用返回其结果

    let response = await fetch('products.json');
    

    解析器会在此行上暂停,直到当服务器返回的响应变得可用时。

    此时fetch()返回的promise将会完成(fullfilled)并赋值给response变量

    接着解析器便会移动到下一行代码

     此时products才能获取到服务器响应返回的数据

        let products = await response.json;
    

      

    4. 超时和间隔

    4.1 setTimeout()

    在指定的时间后执行一段代码.

    setTimeout前两个参数必填,最后一个参数选填

    第一个参数为要超时执行的函数

    第二参数为超时事件

    第三个为传入函数中参数(可选)

    则这段代码效果为: 在执行sayHi函数前,系统将停留2000毫秒,并且传递‘Mr. GoodLooking’给sayHi()函数

    function sayHi(who) {
      alert('Hello Mr. Universe!');
    }
    
    let myGreeting = setTimeout(sayHi, 2000, 'Mr. GoodLooking');

    清除(取消)超时

    clearTimeout(myGreeting);
    

      

    4.2 setInterval()

    以固定的时间间隔,重复运行一段代码.

    第二个参数表示每隔1000毫秒执行一次函数displayTime()

    function displayTime() {
       let date = new Date();
       let time = date.toLocaleTimeString();
       document.getElementById('demo').textContent = time;
    }
    
    const createClock = setInterval(displayTime, 1000);
    

      

     清除(取消)间隔

    const myInterval = setInterval(myFunction, 2000);
    
    clearInterval(myInterval);
    

      

    4.3 requestAnimationFrame()

    setInterval()的现代版本;在浏览器下一次重新绘制显示之前执行指定的代码块,从而允许动画在适当的帧率下运行,而不管它在什么环境中运行.

    function draw() {
       // Drawing code goes here
       requestAnimationFrame(draw);
    }
    
    draw();
    

      

    参考资料:

    https://developer.mozilla.org/zh-CN/docs/Learn/JavaScript/Asynchronous

  • 相关阅读:
    jsp_Scriptlet
    jsp_注释
    Http状态码详解
    Tomcat服务器的安装和配置
    【BZOJ 1018】线段树 **
    【BZOJ 2054】 2054: 疯狂的馒头 (并查集特技)
    【BZOJ 1969】 1969: [Ahoi2005]LANE 航线规划 (树链剖分+线段树)
    【BZOJ 1880】 [Sdoi2009]Elaxia的路线 (最短路树)
    【UOJ 79】 一般图最大匹配 (✿带花树开花)
    【UOJ 34】 多项式乘法 (FFT)
  • 原文地址:https://www.cnblogs.com/leftstan/p/14800097.html
Copyright © 2020-2023  润新知