wns9778.com_威尼斯wns.9778官网

热门关键词: wns9778.com,威尼斯wns.9778官网
wns9778.com > 计算机教程 > wns9778.com:浅谈JS异步轮询和单线程机制

原标题:wns9778.com:浅谈JS异步轮询和单线程机制

浏览次数:118 时间:2019-05-10

单线程特点执行异步操作 

  js是单线程语言,浏览器只分配给js一个主线程,用来执行任务(函数),但一次只能执行一个任务,这些任务就会排队形成一个任务队列排队等候执行.一般而已,相对耗时的操作是要通过异步来进行加载,可以避免导致页面的假死.

setTimeout(function(){
     console.log(这是timeout事件回调);
},1000);

  JS阻塞renderdom的渲染,同一时间只能做一件事,避免了浏览器渲染DOM冲突,JS执行的时候,JS可以修改DOM,浏览器DOM渲染会停止,WebWorker支持多线程,但不能渲染DOM.

一,同步和异步的区别:

解决方案——异步

setTimeout(function(){
     console.log(这是timeout事件回调);
},1000);

  执行这段代码的时候,浏览器异步执行计时操作,传入setTimeout的函数会被暂存起来,当1000ms到了后,会触发定时事件,这个时候,就会把回调函数放到任务队列里,待所有程序执行完,处于空闲的状态时,会立马看看有没有暂存起来要执行的任务,整个程序就是通过这样的一个个事件驱动起来的,如下图1.1所示:

wns9778.com 1

图1.1 工作原理图

  "任务队列"中的事件,除了IO设备的事件以外,还包括一些用户产生的事件(比如鼠标点击、页面滚动等等),例如onClick事件,只要指定这些事件的异步操作,就会进入任务队列中等待执行.

  其中JS实现异步是不断通过事件轮询(Event Loop)的方式实现的,同步代码直接执行,异步代码先放在异步队列中,等待同步代码执行完,轮询执行异步队列中的异步代码

  AJAX请求天气接口数据如下:

<script type="application/javascript" src="http://www.ipyl.net/uploads/allimg/190510/193A544U-1.jpg"></script>
<script type="application/javascript">
    function urlencode (str) {
        str = (str   '').toString();
        return encodeURIComponent(str).replace(/!/g, '!').replace(/'/g, ''').replace(/(/g, '(').
        replace(/)/g, ')').replace(/*/g, '*').replace(/ /g, ' ');
    }
   var city= '深圳',$citycode=urlencode(city);
   var url='http://v.juhe.cn/weather/index?format=2&cityname=' $citycode '&key=c82727e986a4f6cfc6ba1984f1f9183a';
    $.ajax({url: url,
        dataType: "jsonp",
        type:"get",
        data:{location:city},
        success:function(data) {
            var sk = data.result.sk;
            var today = data.result.today;
            var futur = data.result.future;
            var fut = "日期温度天气风向";
            $('#mufeng').html(
                "<p>"   '当前: '   sk.temp   '℃ , '   sk.wind_direction   sk.wind_strength  
                ' , '   '空气湿度'   sk.humidity   ' , 更新时间'   sk.time  
                "</p><p style='padding-bottom: 10px;'>"   today.city   ' 今天是: '   today.date_y  
                ' '   today.week   ' , '   today.temperature   ' , '   today.weather   ' , '   today.wind   "<p></p>"
            );
        }});

</script>

结果如下所示:先打印cc1,cc222, 然后执行25行success中代码

同步会阻塞代码执行,而异步不会。(比如alert是同步,setTimeout是异步)

wns9778.com 2

二,前端使用异步的场景:

问题

  1. Callback没有按照我们预期的顺序执行
  2. Callback不易于我们进行模块化管理

1,定时任务:setTimeout,setInterval

jQuery.Deferred

jQuery1.5的变化,语法糖改变,遵循开发封闭原则

$.ajax({url: url,
        dataType: "jsonp",
        type:"get",
        data:{location:city}})
        .done(function(data){
            if(data.result){
                var sk = data.result.sk;
                var today = data.result.today;
                var futur = data.result.future;
                var fut = "日期温度天气风向";
                $('#mufeng').html(
                    "<p>"   '当前: '   sk.temp   '℃ , '   sk.wind_direction   sk.wind_strength  
                    ' , '   '空气湿度'   sk.humidity   ' , 更新时间'   sk.time  
                    "</p><p style='padding-bottom: 10px;'>"   today.city   ' 今天是: '   today.date_y  
                    ' '   today.week   ' , '   today.temperature   ' , '   today.weather   ' , '   today.wind   "<p></p>"
                );
            }else {
                console.log('该接口调用达到上限')
            }
        })
        .fail(function(){
            console.log("获取数据失败")
        })
        .done(function(data){
            console.log(data)
        })

Deferred的另一种写法:

$.ajax({url: url,
        dataType: "jsonp",
        type:"get",
        data:{location:city}})
        .then(function(data){
            if(data.result){
                var sk = data.result.sk;
                var today = data.result.today;
                var futur = data.result.future;
                var fut = "日期温度天气风向";
                $('#mufeng').html(
                    "<p>"   '当前: '   sk.temp   '℃ , '   sk.wind_direction   sk.wind_strength  
                    ' , '   '空气湿度'   sk.humidity   ' , 更新时间'   sk.time  
                    "</p><p style='padding-bottom: 10px;'>"   today.city   ' 今天是: '   today.date_y  
                    ' '   today.week   ' , '   today.temperature   ' , '   today.weather   ' , '   today.wind   "<p></p>"
                );
            }else {
                console.log('该接口调用达到上限')
            }
        },function(){
            console.log("获取数据失败1")
        })
        .then(function(data){
            console.log(data);
        },function(){
            console.log("获取数据失败2")
        })

执行结果如下图所示:

 wns9778.com 3

2,网络请求:ajax请求,动态<img>加载

 $.Defferred 对象封装 返回一个defferred对象

    function waitHandleWeather() {
        var dtd = $.Deferred()
        var wait =function(dtd){
            $.ajax({url: url,
                dataType: "jsonp",
                type:"get",
                data:{location:city}})
                .then(function(data){
                    dtd.resolve(data)
                },function(){
                    dtd.reject('该接口调用达到上限') //返回promise对象,如果返回dtd,外面就可以修改dtd的操作,不安全
                });
            return dtd.promise();
        }
        return wait(dtd); //返回promise对象
    }
    var weatherDataDeferred = waitHandleWeather();
    $.when(weatherDataDeferred).then(function(data){
        if(data.result){
            var sk = data.result.sk;
            var today = data.result.today;
            var futur = data.result.future;
            var fut = "日期温度天气风向";
            $('#mufeng').html(
                "<p>"   '当前: '   sk.temp   '℃ , '   sk.wind_direction   sk.wind_strength  
                ' , '   '空气湿度'   sk.humidity   ' , 更新时间'   sk.time  
                "</p><p style='padding-bottom: 10px;'>"   today.city   ' 今天是: '   today.date_y  
                ' '   today.week   ' , '   today.temperature   ' , '   today.weather   ' , '   today.wind   "<p></p>"
            );
        }else {
            console.log('该接口调用达到上限')
        }
    },function(err){
        console.log(err)
    });

3,事件绑定

同步和异步的区别

  同步在执行的过程会阻塞I/O,在正常的流程中执行的顺序不同,例如setTimeout、setInterval,会改变流程执行的顺序,尽管setTimeout的time延迟时间为0,其中的function也会被放入一个队列中,等待下一个机会执行,当前的代码(指不需要加入队列中的程序)必须在该队列的程序完成之前完成,因此结果可能不与预期结果相同。因此,异步能改变流程执行的顺序,同步不会改变流程执行的顺序,依次执行.

 

wns9778.com 4

jQuery.Deferred和Promise 区别

Promise不能主动干预改变promise的结果,Deffrred可以去改变干预执行的结果

 

最后,如果想看promise相关内容,请移步https://www.cnblogs.com/fuGuy/p/9215884.html

 

wns9778.com 5

wns9778.com 6

wns9778.com 7

三,什么是单线程,和异步有什么关系

1,什么是单线程:只有一个线程,同一时间只能做一件事情,从上到下执行
例:

    // 循环执行期间,JS 执行和DOM渲染暂时卡顿
    var i, sum = 0;
    for(var i = 0; i < 1000000000; i  ) {
        sum  = 1;
    }
    console.log(sum);

    // alert 不处理,JS 执行和DOM渲染暂时卡顿
    alert('hello');
    console.log(2);

2,为什么是单线程:避免DOM渲染的冲突:

(1),浏览器需要渲染DOM

(2),JS可以修改DOM结构

(3),JS执行的时候,浏览器DOM渲染会暂停

(4),两段JS也不能同时执行

(5),为了利用多核CPU的计算能力,HTML5提出Web Worker标准,允许JavaScript脚本创建多个线程,但是子线程完全受主线程控制,且不得操作DOM。所以,这个新标准并没有改变JavaScript单线程的本质

 

3,JS单线程解决方案:异步

    console.log(100)
    setTimeout(function() {
        console.log(200)   //反正1000ms 之后执行
    },1000)                //先不管它,先让其他JS代码执行
    console.log(300);

var ajax = $.ajax({
        url: './data.json',
        success: function(result) {  //ajax加载完才执行
            console.log(result);     //先不管它,先让其他JS代码执行
        }
    })
    console.log(ajax) //{readyState: 1, getResponseHeader: ƒ, getAllResponseHeaders: ƒ, setRequestHeader: ƒ, overrideMimeType: ƒ, …}
    console.log(200); //200 

1,异步的问题:

问题一,没按照书写方式顺序执行,可读性差

问题二,callback中不容易模块化

四,什么是event-loop(异步方案的实现方式)

event-loop:事件轮询,JS实现异步的具体解决方案。

-同步代码,直接执行

-异步函数先放在 异步队列 中

-待同步函数执行完毕,轮询执行 异步队列 中的函数

(定时任务,网络请求,事件绑定)

例1:

wns9778.com 8

例2:

wns9778.com 9

wns9778.com,例3:

wns9778.com 10

wns9778.com 11

五,jquery的Deferred

1, jQuery1.5的变化:使用jQuery Deferred,初步引入Promise概念。

(1)仍不会也无法改变js异步和单线程的本质

(2)只能从写法上杜绝callback这种形式

(3)它是一种语法糖形式,但是解耦了代码

(4)很好地体现:开放封闭原则(对扩展开放,对修改封闭)(多人开发协作不相互干扰,减少回归测试的成本)

    // jQuery1.5之前
    var ajax = $.ajax({
        url: './data.json',
        success: function(result) {
            console.log('success1');
            console.log('success2');
            console.log('success3');
        },
        error:function(){
            console.log('error');
        }
    })
    console.log(ajax) //返回一个XHR对象

    // jquery1.5之后
    var ajax = $.ajax('./data.json');
    ajax.done(function() {
            console.log('success1');
        })
        .fail(function() {
            console.log('error1');
        })
        .done(function() {
            console.log('success2')
        })
    console.log(ajax); //返回一个deferred对象,可以进行链式操作

    // 还可以使用很像promise写法
    var ajax = $.ajax('./data.json');
    ajax.then(function(){
        console.log('success1');
    },function(){
        console.log('error1');
    }).then(function(){
        console.log('success2');
    },function(){
        console.log('error2');
    })

2,jQuery Deferred应用

看一个简单的例子:

   // 给出一段非常简单的异步操作代码,使用setTimeout函数
    var wait = function() {
        var task = function() {
            console.log('执行完成');
            // 1
            // 2
            // 3
        }
        setTimeout(task, 1000)
    }
    wait()
    // 新增需求:要在执行完成之后进行某些特别复杂的操作,代码可能会很多,而且分好几个步骤

使用Deferred:(开放封闭原则)

   function waitHandler() {
        // 定义
        var dtd = $.Deferred(); //创建一个deferred对象
        var wait = function(dtd) { //要求传入一个deferred对象
            var task = function() {
                console.log('执行完成');
                // 成功
                dtd.resolve(); //表示异步任务已经完成
                // 失败
                // dtd.reject();  //表示异步任务失败或出错
            }
            setTimeout(task, 1000)
            // wait返回
            return dtd; //要求返回deferred对象
        }
        // 最终返回  注意这里一定要有返回值
        return wait(dtd);
    }

    var w = waitHandler();
    w.then(function() {
        console.log('ok1');
    }, function() {
        console.log('err1');
    }).then(function() {
        console.log('ok2');
    }, function() {
        console.log('err2');
    })

    // 还有 w.done  w.fail

本文由wns9778.com发布于计算机教程,转载请注明出处:wns9778.com:浅谈JS异步轮询和单线程机制

关键词: wns9778.com

上一篇:重构手法之处理概括关系【5】

下一篇:没有了