一年经验菜鸟前端眼中的异步编程

前端开发必不可少,什么是异步编程
由于javascript语言是一门“单线程”的语言,所以,javascript就像一条流水线,仅仅是一条流水线而已,要么加工,要么包装,不能同时进行多个任务和流程。
而作为前端开发,在面试与工作中相信大家一定被问过或经常需要用到异步编程,那么什么是异步编程呢?

首先我们先区分一下什么是同步编程,什么是异步编程。
同步编程:我们都知道代码的执行顺序是自上而下执行的,那么同步就是需要每一个任务都完成以后再去执行下一个任务,执行顺序与排列顺序是一致的。坏处,只要有一个任务耗时很长,后面任务都必须排队等着,常见的浏览器无响应,死循环。
异步编程:每一个任务有一个或多个回调函数,前一个任务执行完后,不是执行下一个任务,而是执行回调函数,后一个任务是不等前一个任务结束就执行的,所以程序的执行顺序与任务的排列顺序是不一致的。
简单的说我们可以将异步编程理解为在约定的时间内完成的操作。
举个简单的例子:

假设你设置了一个第二天 7:00 的闹钟,那么我们设置完,是一直在等待闹钟的提醒,再去做下一件事,还是去做别的事情,相信大家都不会傻傻的在那等,在编程里这就异步编程。

异步编程怎么判断:是否阻塞 ? 同步阻塞 ,异步不阻塞。
那么常见的异步编程有什么呢?
setTimeout
Ajax
Promise
async函数
接下来我们通过代码看看异步编程是如何执行的

定时器(setTimeOut)
在规定的时间内完成操作: 点击按钮,会打印“我先执行” 接着打印 “执行定时器”。 可以看到虽然时间设置为0,但是定时器里的任务并不是先被执行

<body>
    <button>点击触发定时器</button>
    <script>
        let btn = document.querySelector('button');
        btn.onclick = function () {
            setTimeout(function () {
                alert('执行定时器');
            }, 0)

        }
        console.log('我先执行');
    </script>
</body>


Ajax (异步JavaScript 和 XML)
首先介绍我们先一下Ajax。

AJAX = Asynchronous JavaScript and XML(异步的 JavaScript 和 XML)
  • Ajax是一种无需重新加载整个页面的情况下,能够更新部分网页的技术。
  • 接着我们通过一个简单的例子来看看ajax的强大(为了方便调用接口我们直接使用网上链接 https://cnodejs.org/api)) ,为了观看效果明显一些会使用点击事件让大家看看触发结果
  • Ajax现代浏览器均支持XMLHTTPRequest对象,但是IE5、IE6需要兼容,下面就不做兼容处理了
body>
    <button onclick="loadXML()">点击获取结果</button>
    <div></div>
    <script>

        function loadXML() {
            let xmlhttp = new XMLHttpRequest();
            xmlhttp.onreadystatechange = function () {
                if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
                    console.log(xmlhttp)
                    document.querySelector('div').innerHTML = JSON.parse(xmlhttp.responseText).data[0].content;
                }
            }
            xmlhttp.open('GET', 'https://cnodejs.org/api/v1/topics', true)
            xmlhttp.send()
            console.log('我先执行了')
        }
    </script>

</body>

可以看得到结果依然是先打印了后面的“我先执行了”


Promise对象

pendding ,fulfilled,rejected
setTimeout(() => console.log(1), 0); // 异步
const p = new Promise((resolve, reject) => {
    console.log(2);                 // 同步
    setTimeout(() => {
        console.log(4)               // 异步优先级低于promise
    }, 0)
    resolve(3);
    console.log(5);                 // 同步
})
console.log(6)                      // 同步
p.then(value => {
    console.log(value);             // 异步
})

console.log(7)                      // 同步

再讲结果之前我们应该了解一下es6的新增的任务队列 是在事件循环之上的(onclick, setTimeout,Ajax)
onclick 是浏览器内核的 DOM Binding 模块来处理的,当事件触发的时候,回调函数会立即添加到任务队列中。
setTimeout 是浏览器内核的 timer 模块进行的延时处理,当时间到达后才会回调添加到任务队列中。
Ajax 是浏览器内核 network 模块在网络请求完成之后,将回调添加到任务队列中。
代码也写了,结果也看了,但是我们为什么要用promise呢?
常见的回答都是解决回调地狱,其实promise也是用于解决异步编程的,
在promise未出现前,我们的异步编程都是通过纯回调解决的
举个例子

// 纯回调
function createdAsync(value,success,catch){
    if (value){
        success()
    }else{
        catch()
    }
}
const success = function (){
    console.log('成功')
}
const catch = catch(){
    console.log('失败')
}

createdAsync(value,success,catch)


// promise 
const promise = createdAsync(value);
setTimeout(()=>{
    promise.then(success,catch);
},1000);

可以看得出 纯回调的形式是先指定回调函数,在我们想要启动异步任务前就必须指定好成功、失败的回调函数,而且我们不能在它完成后在指定回调函数,等他执行完毕已经获取不到数据了;
而 promise是通过执行一个函数,这个函数返回一个promise对象,异步操作是在这个Promise对象内部进行的,也就是Promise构造函数执行时立即调用executor 函数,此时异步任务开始了,但是并不需要指定成功、失败的回调函数。
可以再在来看看前面的代码(我们将代码写的简短一些)

const p = new Promise((resolve, reject) => {
    console.log("executor执行器函数"); //  executor执行器函数
    // 异步任务
    resolve("异步")
})
p.then(value => {
    console.log(value);
})
console.log("new Promise 之后")

打印结果是: ”executor执行器函数“ 、”new Promise 之后“ 、“异步”



所以promsie其实不只是解决回调地狱问题,而说到了回调地狱,其实async函数显得更加优化。

Async函数

Generator
// 以往定义promise的时候
  new Promise((resolve,reject)=>{
    console.log('开始');
    resolve('异步');
  }).then(value => {console.log(value)})
// async函数
  async function fn(){}
  console.log(fn())  // Promise{<fulfilled>:undefined}

可以看得出async 的返回值就是一个Promise对象 并且默认返回一个执行结果为成功的Promise对象,也就是 new Promise() 的语法糖
接着我们看看 async 下的await

// promise
const promise = new Promise((resolve, reject) => {
    resolve('异步');
})

promise.then(value => {
    console.log(value)
})

// async
async function fn(callback) {
    const val = await callback;
    console.log(val)
}

fn(promise)
}

可以看得出await 就是then的语法糖
接着我们看看这个语法糖为我们解决了什么问题

// promise
new Promise((resolve, reject) => {
    resolve(1);
}).then(value => {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            resolve(value + 1)
        })
    });
}).then(value => {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            resolve(value + 1)
        })
    });
}).then(value => {
    console.log(value + 1)
})
console.log('我先')

// ascyn 

async function fn() {
    const one = await new Promise((resolve, reject) => {
        resolve(1)
    })
    const two = await new Promise((resolve, reject) => {
        resolve(one + 1)
    })
    console.log(two);
    console.log('我先')
}

fn()


可以看得出 promise的执行会 先打印出 “我先”,而asyn函数 会将异步执行完毕再进行下面的操作,所以async函数不仅实现了异步编程,并且在代码的上来说执行顺序与排列顺序是一致的。
文中说的内容偏入门级别,也是结合自己所学以及理解。
最后想说的是随着前端开发的不断发展,前端开发人员掌握的技术已经不再是之前的html+css了(俗称的切图仔),并且前端开发人员需要掌握的技术不亚于后端了,甚至需要掌握一些后端知识

如果你现在也想学习前端开发技术,在学习前端的过程当中有遇见任何关于学习方法,学习路线,学习效率等方面的问题,你都可以申请加入我的Q群:前114中6649后671,里面有许多前端学习资料 大厂面试真题免费获取,希望能够对你们有所帮助。


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