JS_同步和异步

day14_同步和异步

  • 同步

    首先,我们要知道,JavaScript的本质是一门浏览器脚本语言,在执行的时候是一行一行的执行,只有前面的代码执行完了才会执行后面的代码。

    JS是单线程语言指的就是这个意思。

  • 异步

    一个任务是否是异步,要看程序员在编写代码的时候是否将这个任务设置为异步,而不是说时间长的任务就一定是异步的,只是通常来讲为了流畅性,编程者会将执行时间长的任务主观的设置为异步。

    那么这里就涉及到一个问题了,怎么将一个任务设置为异步?

    JS中最基础的有两种方式——setTimeout函数和setInterval函数。

    • 循环打印“红”、“黄”、“绿” 灯
    // 红灯
    function first(red, yellow, green) {
        setTimeout(function () {
            console.log("红");
            // yellow(green,red,yellow)
            second(yellow, green, red);
        }, 1000)
    }
    
    // 黄灯
    // yellow(green,red,yellow)
    function second(yellow, green, red) {
        setTimeout(function () {
            console.log("黄");
            // green(red,yellow,green)
            third(green, red, yellow);
        }, 1000)
    }
    
    // 绿灯
    // green(red,yellow,green)
    function third(green, red, yellow) {
        setTimeout(function () {
            console.log("绿");
            first(red, yellow, green);
        }, 1000)
    }
    first(second, third, first);
    
    红绿灯.jpg
    • 异步加载图片
    class Box {
        constructor(time) {
            setTimeout(() => {
                var img = new Image();
                img.src = "./img/36-.jpg";
                img.addEventListener("load", e => {
                    this.loadHandler(e);
                }) 
            }, time)
        }
        loadHandler(e) {
            var evt = new Event("loadFinish");
            evt.img = e.currentTarget;
            document.dispatchEvent(evt);
        }
    }
    
    class Ball {
        constructor(time) {
            setTimeout(() => {
                var img = new Image();
                img.src = "./img/37.jpg";
                img.addEventListener("load", e => {
                    this.loadHandler(e);
                })
            }, time)
        }
        loadHandler(e) {
            var evt = new Event("loadFinish");
            evt.img = e.currentTarget;
            document.dispatchEvent(evt);
        }
    }
    
    class Main {
        arr = [];
        constructor() {
            document.addEventListener('loadFinish', e => {
                this.loadHandler(e);
            })
        }
        loadHandler(e) {
            this.arr.push(e.img);
            if (this.arr.length === 2) {
                console.log(this.arr.reduce((value, item) => value + item.width, 0));
            }
        }
    }
    
    var main = new Main();
    var box = new Box(2000);
    var ball = new Ball(1000);
    //页面加载3秒后,显示两张图片宽度之和
    
    • HTML页面加载顺序

      1. DOM的创建 script的加载,css的加载
      2. 形成CSS样式树,与DOM样式树合并,形成渲染树
      3. 异步加载所有图片
      4. 全部加载完成
    • async

      async 相对于页面的其余部分异步地执行(当页面继续进行解析时,脚本将被执行)

      如果既不使用 async 也不使用 defer:在浏览器继续解析页面之前,立即读取并执行脚本。

      注意:async 属性仅适用于外部脚本(只有在使用 src 属性时)。

    • defer

      如果脚本不会改变文档的内容,可将 defer 属性加入到 script 标签中,以便加快处理文档的速度。

      因为浏览器知道它将能够安全地读取文档的剩余部分而不用执行脚本,它将推迟对脚本的解释,直到文档已经显示给用户为止。

      注意: 只有IE支持

2.异步转同步

  • async

    异步阻塞变为同步,只针对promise,对于setTimeout不起作用

async function fn(){
    //async函数中return就会执行这个函数执行返回的promise的resolve方法
    //因此可以在then中获取
    return 1;
}
//async函数执行后就是返回一个Promise
var a=fn();
a.then(function(value){
    console.log(value);
})
  • 当async修饰的函数的函数体为空时

    1. 获取fn的值是Promise
    2. 状态是resolved
async function fn(){
    
}
console.log(fn());
//Promise {<resolved>: undefined}
  • async与await
async function fn(){
    console.log("a");
    // 异步阻塞,变成了同步
    await loadImage("./img/2-.jpg").then(function(img){
        console.log(img);
    });
    console.log("b");
}

function loadImage(src){
    return new Promise(function(resolve,reject){
        let img=new Image();
        img.src=src;
        img.onload=function(){
            resolve(img);
        }
    })
}
fn();
//a
//打印img
//b
  • await阻断Promise的异步,等待其中的resolve
async function fn(){
    console.log("aaa");
    // 只有Promise的状态发生改变时才会继续向下执行await后面的内容
    await new Promise(function(resolve,reject){
    }).then(function(){
        console.log("bbb");
    }).catch(function(){
        console.log("ddd");
    })
    console.log("ccc");
}
fn();
//aaa
  • 用async和await处理promise.all()
function loadImage(src){
    return new Promise(function(resolve,reject){
        let img = new Image();
        img.src = src;
        img.onload = function(){
            resolve(img);
        }
    })
}

class Promise1{
    static async all(arr){
        let list = [];
        for(let i = 0; i < arr.length; i++){
            //将promise异步转换为同步等待
            await arr[i].then(function(img){
                list.push(img);
            })
        }
        return list;
    }
}

var arr = [];
for(let i = 2; i < 80; i++){
    arr.push(loadImage("./img/" + i + "-.jpg"));
}

Promise1.all(arr).then(function(list){
    console.log(list);
})
  • 实现循环打印 “红黄绿" 灯
function showLight(color,time){
    return new Promise((resolve,reject)=>{
        setTimeout(()=>{
            resolve(color);
        },time)
    });
}

async function show(){
    await showLight("红色",2000).then(color=>console.log(color));
    await showLight("黄色",2000).then(color=>console.log(color));
    await showLight("绿色",2000).then(color=>{
        console.log(color);
        show();
    });
}

show()
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 201,468评论 5 473
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 84,620评论 2 377
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 148,427评论 0 334
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,160评论 1 272
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,197评论 5 363
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,334评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,775评论 3 393
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,444评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,628评论 1 295
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,459评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,508评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,210评论 3 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,767评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,850评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,076评论 1 258
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,627评论 2 348
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,196评论 2 341

推荐阅读更多精彩内容

  • Tif_Lib阅读 461评论 0 1
  • 最基础的异步是setTimeout和setInterval函数很常见,但是很少人有人知道其实这就是异步,因为它们可...
    FF_C阅读 427评论 0 0
  • 参考1 vue js 实例 结果 f4 f3 f1 f2 setTimeout 是异步的,time == 0 也一样
    思念LY阅读 220评论 0 0
  • "use strict";function _classCallCheck(e,t){if(!(e instanc...
    久些阅读 2,027评论 0 2
  • 第一章: JS简介 从当初简单的语言,变成了现在能够处理复杂计算和交互,拥有闭包、匿名函数, 甚至元编程等...
    LaBaby_阅读 1,630评论 0 6