异步编程相关整理

JS异步编程

js是单线程语言:js执行环境中,负责执行代码的线程只有一个。为了防止代码运行阻塞,所以js分为同步模式和异步模式。

同步模式

等待任务依次执行,上一个任务结束之后,下一个才执行。
每当一个函数要被执行的时候,这个函数会被进入调用栈,在调用栈中执行完毕之后出栈。

异步模式

不会等待这个任务的结束才去开始下一个任务,开启过后立刻执行下一个任务,后续逻辑一般会用回调函数的方法定义。

调用栈(call stack):函数执行的主进程,可以理解为一个执行中的调用表。
消息队列(Queue):又称回调队列,可以理解为一个即将调用的表。回调队列中的任务称之为宏任务。
event loop事件轮询:监听消息队列和调用栈,当调用栈的程序全部执行完毕之后,就会去查看消息队列是否有程序执行(开始从消息队列中取出第一个消息放入调用栈当中去执行)。
下面举一个例子
例子1
当遇见了setTimeout函数时,会将setTimeout函数放入web apis中,当执行栈中的函数全部运行完之后,事件轮询会去查找消息队列中是否有任务执行。
这里例子中web apis中有两个seitimeout函数,当1s后第一个settimeout函数被放入消息队列,事件轮询找到了第一个函数,然后将其放入到执行栈中去执行,1.8s之后第二个settimeout的函数被放入到消息队列中,轮询查找到后被压入到执行栈中执行。由于第二个settimeout函数中还包含了一个settimeout,此时这个新的settimeout又被压入到web api中,等待被放入到消息队列。
在这里插入图片描述

Promise

Promise只有状态为resolved或rejected的时候(看是否执行了resolve()或者rejected()函数),then方法才会执行。
注意:Promise.then()返回的依然是一个Promise对象,这样就解决了回调地狱的问题。所以第二个then里面的值就是上一个对象的

const promise = new Promise(function(resolve, reject) {
    // resolve(100) //成功,参数作为一个成功之后的返回值

    reject(new Error('promise rejected')) //失败,一般返回一个错误的对象
})

promise.then((resolve) => {
    //成功之后的回调
    console.log(resolve)
}, (error) => {
    //失败的回调
    console.log(error)
})

例子:用promise实现一个ajax请求

function ajax(url) {
    return new Promise(function(resolve, rejected) {
        var xhr = new XMLHttpRequest()
        xhr.open('GET', url)
        xhr.responseType = 'json'
        xhr.onload = function () {
            if(this.status === 200) {
                resolve(this.response)
            } else {
                rejected(new Error(this.statusText))
            }
        }
        xhr.send()
    })
}
ajax('./api/user.json').then((resolve) => {
    console.log(resolve)
}, (rejected) => {
    console.log(rejected)
})

Promise异常处理

只要promise函数有报错,then方法都会异常处理,并不只是在promise函数的reject里面写才会用作异常处理。
Promise异常处理中,链式调用的时候,如果只用then方法进行异常捕获,那其实后面的then方法捕获的是前一个的异常,并不是捕获的自身的异常,因为then方法是前一个promise的回调。所以在promise异常处理中,一般都是用catch方法做异常捕获,catch方法捕获的是当前回调的异常,不是上一个回调的异常。

ajax('./api/user.json')
    .then((resolve) => {
        console.log(resolve)
        // return ajax('./api/uss.json')
    })
    .then((resolve) => {
        console.log(resolve)
        return ajax('./api/uss22.json') //不存在
    })
    .then((resolve) => {
        console.log(resolve)
        return ajax('./api/uss33.json') //不存在
    })
    .catch((rejected) => {
        console.log(rejected)
    })

Promise静态方法

Promise.resolve()快速的把一个值转化为一个Promise对象。如果传值传的本身就是一个Promise对象,那么则返回这个Promise对象。如果传入了一个对象,这个对象中有then函数,那么可以将这个函数作为一个Promise返回
Promise.reject()快速把一个值转化法一个一定失败的promise对象

Promise.resolve('foo').then( resolve => {console.log(resolve)})
//等同于
new Promise(function(resolve, reject) {
    resolve('foo')
})

Promise.resolve({
    then: function(onFullfilled, onRejected) {
        onFullfilled('foo')
    }
}).then((resolve) => {
    console.log(resolve) //foo
})

Promise并行执行

Promise.all()同时进行,全部任务结束才会返回值。接收一个全是Promise对象的数组,返回一个全新的Promise对象,拿到的结果是一个数组,每个值都是传入的Promise的结果。如果有一个Promise失败,那么会直接返回。
Promise.race()只会等待第一个结束任务。用于类似AJAX请求超时的实现

Generator异步方案

yield 返回的内容作为.next()的结果

function * main () {
    yield ajax('./api/user.json')
    yield ''
}
const g = main()
const result = g.next()
result.value.then(data => {
    // console.log(data)
    const result2 = g.next()
    console.log(result2.value)
})

Generator执行器

function * main () {
    try {
        yield ajax('./api/user.json')
        yield ajax('./api/user1.json')
    } catch (e) {
        console.log(e)
    }
}

// const result = g.next()
// result.value.then(data => {
//     // console.log(data)
//     const result2 = g.next()
//     console.log(result2.value)
// })
function co (generator) {
    const g = generator()
    function handleResult (result) {
        if(result.done) return //生成器结束
        result.value.then(data => {
            handleResult(g.next())
        }, error => {
            g.throw(error)
        })
    }
    handleResult(g.next())
}
co(main)

Aysnc/Await语法糖

Aysnc其实是生成器的一个语法糖,返回一个Promise对象,这个函数的返回值是这个promise状态值的resolve值。
await是一个表达式,如果后面不是一个promise对象,就直接返回对应的值。那如果后面是一个promise对象,await将等待这个promise对象的resolve状态值的value,且将这个值返回前面的变量。

async function main () {
    try {
        await ajax('./api/user.json')
        console.log(1)
        await ajax('./api/user.json')
        console.log(2)
    } catch (e) {
        console.log(e)
    }
}

const g = main()
g.then(data => {
    console.log(data)
})

本节过程中所使用的工具

html-webpack-pluging
1.为html文件中引入的外部资源如script、link动态添加每次compile后的hash,防止引用缓存的外部文件问题
2.可以生成创建html入口文件,比如单页面可以生成一个html文件入口,配置N个html-webpack-plugin可以生成N个页面入口

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值