• js同步-异步-回调


    出处:https://blog.csdn.net/u010297791/article/details/71158212
    (1)上面主要讲了同步和回调执行顺序的问题,接着我就举一个包含同步、异步、回调的例子。

        let a = new Promise(//声明了一个Promise回调函数,能够使用then
      function(resolve, reject) {
        console.log(1)
        setTimeout(() => console.log(2), 0)
        console.log(3)
        console.log(4)
        resolve(true)
      }
    )
    a.then(v => {
      console.log(8)
    })
     
    let b = new Promise(
      function() {
        console.log(5)
        setTimeout(() => console.log(6), 0)
      }
    )
     
    console.log(7)


         在看正确结果之前,我先进行分析题目(访问顺序:同步 => 异步 => 回调):
        1)看同步代码:a变量是一个Promise,Promise的异步指的是他的then()和catch()方法,Promise本身还是同步的,所以这里先执行a变量内部的Promise同步代码。(同步优先)
        console.log(1)
        setTimeout(() => console.log(2), 0) //回调
        console.log(3)
        console.log(4)
        2)Promise内部有4个console,第二个是一个setTimeout回调(回调垫底(意思就是你先让它等着),所以暂时不输出)。所以这里先输出1,3,4,回调的方法丢到消息队列中排队等着。
        3)接着执行resolve(true),进入then(),then是异步,下面还有同步没执行完呢,所以then也去消息队列排队等候。(异步靠边)
        4)b变量也是一个Promise,和a一样,同样是同步的,执行内部的同步代码,输出5,setTimeout是回调,去消息队列排队等候,这里输出5。
    5)最下面同步输出7。
    6)现在同步的代码执行完了,JavaScript就跑去消息队列呼叫异步的代码:异步,出来执行了。这里只有一个异步then,所以输出8。
   7)此时,异步也over,轮到回调函数:回调,出来执行了。这里有2个回调在排队,他们的时间都设置为0,所以不受时间影响,只跟排队先后顺序有关。则先输出a里面的回调2,最后输出b里面的回调6。
   8)最终输出结果就是:1、3、4、5、7、8、2、6。

    (2)分析下面这个例子的执行顺序

    var Pro = function () {
       //返回一个Promise对象
       return new Promise(function (resolve, reject) {
        //模拟接口调用
        setTimeout(function () {//1,回调等待,同步执行
         resolve(true);//4,然后进入then函数
        }, 1000);
       })
      };
      var Pro2 = function () {
       //返回一个Promise对象
       return new Promise(function (resolve, reject) {
        //模拟接口调用
        setTimeout(function () {//2,回调等待
         resolve(‘Pro2成功执行’);//9,访问另一个then
        }, 1000);
       })
      };
      
      Pro().then(function(data){//3异步等待
       var val = data;//5,resolve传入的data是true
       console.log(val)//6,所以先输出true
       if (val) {
        console.log(1111)//7,再输出1111
        return Pro2()//8
       }
       
      }).then(function(data1){//8异步等待
       console.log(data1)//10,输出Pro2成功执行
      })

    输出:


    (3)async/await(代替了promise)
    可以先看http://www.ruanyifeng.com/blog/2015/05/async.html
    async 函数返回一个 Promise 对象,可以使用 then 方法添加回调函数。当函数执行的时候,一旦遇到 await 就会先返回,等到触发的异步操作完成,再接着执行函数体内后面的语句。
    下面是一个例子。
    //getStockSymbol(name)和getStockPrice(symbol)都是异步函数,这样才能使用
    //await进行声明,当两个异步函数调用完后,返回一个Promise对象,其值为
    //stockPrice
    async function getStockPriceByName(name) {
      var symbol = await getStockSymbol(name);
      var stockPrice = await getStockPrice(symbol);
      return stockPrice;
    }

    //然后就可以使用then函数来得到返回的值result == stockPrice
    getStockPriceByName('goog').then(function (result){
      console.log(result);
    });


    //如果在函数function (result){}中运行了比较复杂的语句最好是加上catch来捕获err,如:
    getStockPriceByName('goog').then(function (result){
      console.log(result);
    }).catch((err) =>{
        console.log(err);
            });

    上面代码是一个获取股票报价的函数,函数前面的async关键字,表明该函数内部有异步操作。调用该函数时,会立即返回一个Promise对象。

    这个东西的使用手法就是:
    首先你先写一个return new Promise的回调function,这个function就不用声明为async,然后就可以在另一个声明为async的函数中使用这个回调function ,使用时前面表明await,await等待的虽然是promise对象,但不必写.then(..),直接可以得到返回值;另一个使用的办法则是直接使用then函数回调,然后用catch函数捕捉错误。


    在async函数中如果有await的声明,只能说后面要进行的操作是异步操作来获得返回值的,如果先后,如:
   

    let c = await count();

   

    let l = await list();
    return {count:c,list:l};
    只是说明两者只是写的时候好像有了个前后关系,但是他们不是同步的,而是异步的,所以他们可以同时进行运算,然后等待两者结果都出来了以后进行拼装罢了


    当函数执行的时候,一旦遇到 await 就会先返回,等到触发的异步操作完成,再接着执行函数体内后面的语句

    我是这么理解promise和async/await两者的使用的,我觉得当要使用过多异步的时候,使用async/await更好,比如:

    var id;
    create(user1,’0x0000002’,10,10).then((result) => {
        if(result){
            console.log(result);
            return owned(user1);  //得到user1创建的tokenID
        }
    }).then((result) => {
        if(result){
            id = result;
            console.log('num is :' + result);
            return sell(result);  //卖掉该token
        }   
    }).then((result) => {
        if(result){
            console.log(result);
            return buy(user2,40,id);  
        }       
    }).catch((err) =>{
        console.log(err);
    });


    当我们想要对一系列回调函数进行有序测试时,如果使用的是then,那么最后看起来真的很繁杂;但是如果使用的是async/await,那么就可以变成:

    var test = async() => {
        try{
            await create(user1,’0x0000002’,10,10);
            var id = await owned(user1);
            await sell(id);
            await buy(user2,40,id);
        }catch(err){
            console.log(err);
        }
    }

    光是看起来就好很多了

    注意:当一个函数被声明为async时,说明它是异步的,说明它的返回值是promise类型的,调用函数后后面可以用then进行返回值的调用,而不是说它的函数中一定要出现await。


  • 相关阅读:
    Java多线程详解——一篇文章搞懂Java多线程
    解析spring事务管理@Transactional为什么要添加rollbackFor=Exception.class(事务失效)
    有参构造器(方法)和无参构造器(方法)的作用(区别)
    JAVA:将类、抽象类、接口当成方法的参数传入
    为什么要有无参构造方法,无参构造的运行原理
    java 如何在listener(监听器) 中使用Spring容器管理bean
    java为什么有些异常throw出去需要在函数头用throws声明,一些就不用?
    用mmap 考os不用考虑, 利用 cache 向量化计算 内存对齐 叶大小 都得考虑 还有原子写入
    位运算 异或 数组中数字出现的次数 II
    程序中有个常量,空间超过了1页,有哪些优化思路
  • 原文地址:https://www.cnblogs.com/wanghui-garcia/p/9507142.html
Copyright © 2020-2023  润新知