Promise笔记1

97 阅读6分钟

Promise

1.什么是异步编译

js是单线程,需要借助系统其他线程,js给系统派发任务,系统完成之后交给js异步编程;先把主任务完成之后,再通过轮询的方式遍历任务队列(不断轮询遍历任务队列)

2.Js异步编译

同步是按照编写的代码顺序执行,异步不按照代码顺序执行

主线程作为一个线程,不能接受多方面请求,如果,当一个事件还没有结束,此时界面无法处理其他请求。为了避免这种情况,通常使用子线程来完成一些耗时长的任务。子线程是独立与主线程的,所以子线程出现堵塞情况也不会影响到主线程的运行。

但是子线程有一个局限:一旦发射就会与主线程失去同步,这也就导致了我们无法确定子线程中的任务什么时候结束,因为当结束之后还需要处理其他任务。为了解决这一问题,js中的异步操作函数往往通过回调函数来进行异步任务的结果处理。

回调函数:函数不是程序员进行调用的,而是由程序调用

异步任务必须指定回调函数,当主线程开始执行异步任务,就是执行相应的回调函数。例如ajax的success,complete,error也都指定了各自的回调函数,这些函数就会加入任务队列中,等待执行。

3.任务排序

任务,先进任务队列则先被执行到。
当有两个文件a和b,并且a文件是依赖与b的,但是如果a文件没有被执行就执行了b,则会报错,因为b里面包含a,但是此时a没有被加载到,所以会找不到会产生错误。此时就需要进行嵌套,将a文件的调用嵌套在b里面。

4.Promise什么时候会使用

promise常用于在获取异步请求,比如我们用的axios就是一个promise

5.Promise是为了解决什么问题

promise就是为了解决层次复杂的回调地狱问题的产生

6.Promise微任务处理机制

then为任务,可以添加多个微任务

// 创建一个Promise构造函数,
// 大括号包含起来的部分是pending准备阶段
// 准备阶段有两种结果:成功resolve(),拒绝reject()
new Promise((resolve,reject)=>{
  // reject('拒绝状态');
  resolve('成功状态');
}).then((value)=>{
  // then方法是对结果进行回调函数处理
  console.log('成功执行的业务处理')
},reason=>console('拒绝业务处理'))
// 后面的reason是对拒绝状态的业务处理

7.同步任务、宏任务、微任务的执行顺序

同步执行的优先级最高>微任务>宏任务
new Promise返回的是一个Promise,Promise.then返回的也是一个Promise

new Promise(resolve => {
            resolve()
            console.log('同步任务1')
        }).then(value => console.log('成功'))
        console.log('同步任务2')

其中new Promise({})这部分是同步任务,和console.log('同步任务2')是顺序执行的
.then()当程序执行到这会把它加载到微任务队列中
显示结果为:同步任务1 同步任务2 成功

8.Promise单一状态与状态中断,基本用法

promise的状态改变之后是不可逆的(此时任务就产生了)不能再进行撤销了
promise只能发送成功或者拒绝其中一个状态
在.then方法中对结果进行回调函数处理时候,如果直接收对拒绝状态的处理(null,reject=>)这个null不能省略,相当于一个占位

9.then返回值的处理技巧

下面的then能接收到上边then的返回值,默认情况下then返回的promise就是成功状态,所以最后一个then进行成功状态的回调函数处(链式)
简单来说:一个Promise对应一个解决方法.then,then需要等待Promise有了状态才会进行处理。

        let p1 = new Promise((resolve, reject) => {
                resolve('fulfilled');
            }).then(value => {
                    console.log(value)
                    return "返回Promise"
                },
                reason => consloe.log('error' + reason)
            )
            .then(value => console.log(value))

输出结果为:fulfilled 返回Promise

10.其他类型的Promise封装

可以将类、对象、方法等都封装为promise,只要有then就会返回一个promise对象,可以直接将其作为promise来进行使用。
下面举例说明一下:

let p1 = new Promise((resolve, reject) => {
                resolve("fulfilled")
            }).then(
                value => {
                    // return new Promise((resolve, reject) => {
                    //     // 返回一个Promise
                    //     resolve("成功")
                    // })
                    // return {
                    //     // 返回的是一个对象的时候接收的值也是一个普通的对象
                    //     name:"xinyi"
                    // }
                    // return {
                    //     // 返回的这个then也是封装成了一个Promise对象
                    //     then(resolve, reject) {
                    //         setTimeout(()=>{
                    //             resolve('这是对象')
                    //         },2000)
                    //     }
                    // }
                    // class Hd {
                    //     then(resolve, reject) {
                    //         setTimeout(() => {
                    //             resolve('这是对象')
                    //         }, 2000)
                    //     }
                    // }
                    // return new Hd()
                    return class {
                        static then(resolve, reject) {
                            resolve("这是一个静态方法")
                        }
                    }
                }
            )
            .then(
                value => console.log(value)
            )

11.将Promise封装到函数里

将Promise封装到函数里面,如果状态没有改变,then也不会执行

 function request() {
            return new Promsie((resolve, reject) => {
                setTimeout(() => {
                    resolve('成功')
                }, 2000)
            })
        }
        // 将Promise封装到函数里面,如果状态没有改变,then也不会执行
        request().then(value => console.log(value))

12.Promise多种错误监测与catch使用

 let p1 = new Promise((resolve, reject) => {
                // reject(new Error('错误的第一种写法'))
                // throw new Error('错误的第二种写法')
                // hd+1     没有定义就是用变量产生的错误
                // resolve("成功")
                reject('拒绝')
            }).then(value => {
                return new Promise((resolve, reject) => {
                    reject('p2')
                })
            })
            .then(value => console.log("当只对成功进行处理"))
            // 当上一个then接收到的promise是一个错误的状态,但是在then里面没有进行相应的错误处理,就会到catch里面进行错误处理
            .catch(error => console.log("对异常的统一处理" + error))
            // 推荐做法就是把catch放到最后来捕获错误

13.使用finally实现异步加载动画

注:元素id会在window下自动生成变量,在js中可以直接通过id进行访问。

.finally(()=>{})不论是成功或者失败状态,都会执行到。

<div>loading</div>
    <script>
        const promise = new Promise((resolve, reject) => {
                resolve('123hhh')
            }).then(msg => {
                console.log('resolve')
            })
            .finally(() => {
                console.log('永远会执行(加载),不管成功或者失败')
            })
    </script>

14.Promise异步加载图片

function loadImg(src) {
            return new Promise((resolve, reject) => {
                // 实例化出一个图片对象
                const image = new Image()
                    // 指定图片的来源就是src
                image.src = src
                    // 当图片加载成功的时候来改变Promise的状态
                image.onload = () => {
                        resolve(image)
                    }
                    // 如果图片加载失败的时候改变它的状态为拒绝状态
                image.onerror = reject
                document.body.appendChild(image)
            })
        }
        // 这个图片加载好之后可以对他进行处理
        loadImg('image/zhengjian.jpg').then(image =>
            image.style.border = "solid 2px #ddd"
        )

15.封装setTimeout定时器

// setTimeout(()=>{
        //     console.log('123')
        // },2000)
        // 用Promise封装一个定时器
        function timeout(delay = 1000) {
            return new Promise(resolve => setTimeout(resolve, delay))
        }
        // 调用这个定时器,并进行操作
        timeout(2000).then(() => {
            console.log("123")
            return timeout(2000)
        }).then(value => {
            console.log("456")
        })

16.构建扁平化的setInterval

<div></div>
    <script>
        function interval(dalay = 1000, callback) {
            return new Promise(resolve => {
                let id = setInterval(() => {
                    callback(id, resolve)
                }, dalay)
            })
        }
        interval(100, (id, resolve) => {
            // clearInterval(id)
            // resolve()
            const div = document.querySelector("div")
            let left = parseInt(window.getComputedStyle(div).left)
            div.style.left = left + 10 + 'px'
            if (left >= 200) {
                clearInterval(id)
                resolve(div)
            }
        }).then(div => {
            return interval(100, (id, resolve) => {
                let width = parseInt(window.getComputedStyle(div).width)
                div.style.width = width - 10 + "px"
                if (width <= 30) {
                    clearInterval(id)
                    resolve(div)
                }
            })
        }).then(div => {
            div.style.backgroundColor = "green"
        })
    </script>

17.script脚本的Promise加载引擎

function loadScript(src) {
            return new Promise((resolve, reject) => {
                // 创建了一个script标签(定义一个脚本节点)
                const script = document.createElement("script")
                    // 将src指向传递过来的src
                script.src = src
                    // 加载之后成功执行的回调函数
                script.onload = () => resolve(script)
                script.onerror = reject
                document.body.appendChild(script)
            })
        }
        loadScript('js/hd.js')
            .then(script => {
                return loadScript('js/houdunren.js')
            }).then(script => {
                houdunren()
            })
function hd() {
    console.log("hd.js")
}
function houdunren() {
    hd()
    console.log('houdunren.js')
}