async+await优雅处理异步

同步与异步

1.同步

一次只能执行一个任务,函数调用后需等到函数执行结束,返回执行的结果,才能进行下一个任务。如果这个任务执行的时间较长,就会导致「线程阻塞」。

/* 例2.1 */
var x = true;
while(x);
console.log("don't carry out");    //不会执行

2.js的单线程与异步

我们知道,js的执行环境是「单线程」
说到js的单线程(single threaded)和异步(asynchronous),很多同学不禁会想,这不是自相矛盾么?其实,单线程和异步确实不能同时成为一个语言的特性。js选择了成为单线程的语言,所以它本身不可能是异步的,但js的宿主环境(比如浏览器,Node)是多线程的,宿主环境通过某种方式(事件驱动,下文会讲)使得js具备了异步的属性。

3.浏览器为耗时的任务开辟另外的线程

js是单线程语言,浏览器只分配给js一个主线程,用来执行任务(函数),但一次只能执行一个任务,这些任务形成一个任务队列排队等候执行,但前端的某些任务是非常耗时的,比如http网络请求定时器事件监听,如果让他们和别的任务一样,都老老实实的排队等待执行的话,执行效率会非常的低,甚至导致页面的假死。所以,浏览器为这些耗时任务开辟了另外的线程,主要包括http请求线程,浏览器定时触发器,浏览器事件触发线程,这些任务是异步的。

4.任务队列

刚才说到浏览器为网络请求这样的异步任务单独开了一个线程,那么问题来了,这些异步任务完成后,主线程怎么知道呢?答案就是回调函数,整个程序是事件驱动的,每个事件都会绑定相应的回调函数,举个栗子,有段代码设置了一个定时器

setTimeout(function(){
    console.log(time is out);
},50);

执行这段代码的时候,浏览器异步执行计时操作,当50ms到了后,会触发定时事件,这个时候,就会把回调函数放到任务队列里。整个程序就是通过这样的一个个事件驱动起来的。
所以说,js是一直是单线程的,浏览器才是实现异步的那个

要实现按顺序打印

function ajax(word) {
    setTimeout(() => {
        console.log(word)
    },1000) 
}
ajax('1')
console.log('2')

上面这段代码,打印出2,1,因为setTimeout是异步,js遇到异步会先挂起,先执行同步任务。

1.用回调的方法解决

function ajax1(word,fn) {
    setTimeout(() => {
        console.log(word)
        fn()
    },1000)
}
ajax1('1',() => {
    ajax1('2',() => {
        ajax1('3',() => {
            ajax1('4',() => {
        
            })
        })
    })
})

如果项目复杂,就会有请求1,请求2,这就是传说中的回调地狱,简称callback hell

2.promise解决方案

function delay(word) {
    return new Promise((resolve,reject) => {
        setTimeout(() => {
            resolve(word)
        },2000)
    })
}

delay('孙悟空')
    .then((word) => {
        console.log(word)
        return delay('猪八戒')
    })
    .then(word => {
        console.log(word)
        return delay('沙悟净')
    })
    .then(word => {
        console.log(word)
    })

3.async+await

function delay(word) {
    return new Promise((resolve,reject) => {
        setTimeout(() => {
            resolve(word)
        },2000)
    })
}
//async+await一定要一起使用,async定义函数,await在async内部使用,等待异步执行完毕
async function start() {
    const word1 = await delay('孙悟空')
    console.log(word1)
    const word2 = await delay('猪八戒')
    console.log(word2)
    const word3 = await delay('沙悟净')
    console.log(word3)
}
start()

下面用一个小球运动的例子来描述




    
    Document
    


    

简单的ajax实现方法

//--------------------回调-------------------------------------------------------------------------
var url = 'https://hq.tigerbrokers.com/fundamental/finance_calendar/getType/2017-02-26/2017-06-10';
var result;

var XHR = new XMLHttpRequest();
XHR.open('GET', url, true);
XHR.send();

XHR.onreadystatechange = function() {
    if (XHR.readyState == 4 && XHR.status == 200) {
        result = XHR.response;
        console.log(result);

        // 伪代码
        var url2 = 'http:xxx.yyy.com/zzz?ddd=' + result.someParams;
        var XHR2 = new XMLHttpRequest();
        XHR2.open('GET', url, true);
        XHR2.send();
        XHR2.onreadystatechange = function() {
            //...
        }
    }
}

//---------promise----------------------------------------------------------------------------------------

var url = 'https://hq.tigerbrokers.com/fundamental/finance_calendar/getType/2017-02-26/2017-06-10';

// Promise封装一个get请求的方法
function getJSON(url) {
    return new Promise(function(resolve, reject) {
        var XHR = new XMLHttpRequest();
        XHR.open('GET', url, true);
        XHR.send();

        XHR.onreadystatechange = function() {
            if (XHR.readyState == 4) {
                if (XHR.status == 200) {
                    try {
                        var response = JSON.parse(XHR.responseText);
                        resolve(response);
                    } catch (e) {
                        reject(e);
                    }
                } else {
                    reject(new Error(XHR.statusText));
                }
            }
        }
    })
}

getJSON(url).then(resp => console.log(resp));

//-----------------------async------------------------------------------------------------------------

function getUrl(url) {
    return new Promise((resolve,reject) => {
        let xhr = new XMLHttpRequest()
        xhr.open('GET',url,true)
        xhr.send()
        xhr.onreadystatechange = function() {
            if(xhr.readyState == 4){
                if(xhr.status == 200) {
                    resolve(JSON.parse(xhr.response))
                }else{
                    reject(new Error(XHR.statusText));
                }
            }
        }
    }) 
}

async function start() {
    const word1 = await getUrl('https://hq.tigerbrokers.com/fundamental/finance_calendar/getType/2017-02-26/2017-06-10')
    console.log(word1)
}
start()

你可能感兴趣的:(async+await优雅处理异步)