笔记——Promise

1. 为什么要用Promise?

  1. 支持链式调用,可以解决回调地域问题(回调地狱:不便于阅读和异常处理)
  2. 指定回调函数的方式更加灵活

2. Promise初体验

// resolve 接收 函数类型的数据
// reject 拒绝 函数类型的数据
const p = new Promise((resolve, reject)=>{
    setTimeout(()=>{
        let n = (0, 100)之间的随机数
        if(n <= 30){
            // 将Promise对象的状态设置为 【成功】
            resolve(n)
        } else {
            // 将Promise对象的状态设置为 【失败】
            reject(n)
        }
    }, 1000)
});
// 调用then方法
p.then((value)=>{
    alert('恭喜中奖啦' + value)
}, (reason)=>{
    alert('再接再厉吧' + reason)
})

3. Promise实践练习——fs读取文件

const fs = require('fs')

// 回调函数 形式
fs.readFile('要读取的文件路径', (err, data) => {
    // 如果出错,抛出异常
    if(err) throw err;
    // 如果成功,打印读取到的文件内容
    console.log(data) 
});

// Promise 形式
let p = new Promise((resolve, reject) => {
    fs.readFile('要读取的文件路径', (err, data) => {
        // 如果出错
        if(err) reject(err)
        // 如果成功
        resolve(data)
    })
});
// 调用then
p.then(value=> {
    // 转换成字符串类型,否则是Buffer类型
    console.log(value.toString())
}, reason => {
    console.log(reason)
})

4. Promise实践练习——ajax请求

// 接口地址: https://api.apiopen.top/getToke
// 随便一个元素绑定点击事件
$('.btn').on('click', function(){
    const p = new Promise((resolve, reject) => {
        // 1.创建对象
        const xhr = new XMLHttpRequest();
        // 2.初始化
        xhr.open('GET', '接口地址');
        // 3.发送
        xhr.send();
        // 4.处理响应结果
        xhr.onreadystatechange = function(){
            if(xhr.readyState === 4){
                // 判断响应状态码
                if(xhr.status >= 200 && xhr.status < 300){
                    // 成功,控制台输出响应体
                    resolve(xhr.response);
                }else {
                    // 失败,控制台输出状态码
                    reject(xhr.status);
                }
            }
        }
    });
    // 调用then
    p.then(value => {
         console.log(value);
    }, reason => {
        console.log(reason);
    });
})

5. Promise封装fs读取文件操作

// 封装一个函数 mineReadFile 读取文件内容
// 参数:path 文件路径
// 返回:promise 对象
// 需要在nodejs环境下运行
function mineReadFile(path){
    return new Promise((resolve, reject) => {
        require('fs').readFile(path, (err, data) => {
            // 读取错误
            if(err) reject(err);
            // 读取成功
            resolve(data);
        })
    });
}
mineReadFile('要读取的文件路径')
.then(value => {
    console.log(value.toString());
}, reason => {
    console.log(reason);
})

6. util.promisify方法进行promise风格转化

// util.promise 方法
// 引入 util 模块
const util = require('util')
// 引入 fs 模块
const fs = require('fs')
// 返回一个新的函数
let mineReadFile = util.promisify(fs.readFile);

mineReadFile('要读取的文件路径')
.then(value => {
    console.log(value.toString)
}, reason => {
    console.log(reason)
})

7. Promise封装ajax请求

// 封装一个函数 sendAJAX 发送 GET AJAX 请求
// 参数 URL
// 返回结果 Promise 对象
function sendAJAX(url){
    return new Promise((resolve, reject) => {
        const xhr = new XMLHttpResquest();
        xhr.responseType = 'json';
        xhr.open('GET', url);
        xhr.send();
        // 处理结果
        xhr.onreadystatechange = function(){
            if(xhr.readyState === 4){
                if(xhr.status >= 200 && xhr.status < 300){
                    resolve(xhr.response);
                }else {
                    reject(xhr.status);
                }
            }
        }
    })
}
sendAJAX('要调用的接口地址')
.then(value => {
    console.log(value);
}, reason => {
    console.warn(reason);
})

8. Promise对象状态属性介绍(PromiseState)

  1. pending变为resolved / fulfilled
  2. pending变为rejected
  3. 说明:只有这两种,且一个promise对象只能改变一次,无论变为成功还是失败,都会有一个结果数据,成功的结果数据一般称为value,失败的结果数据一般称为reason

9. Promise对象结果值属性介绍(PromiseResult)

  1. 保存着异步任务【成功/失败】的结果
  2. resolve / reject可以设置PromiseResult的值

10. Promise工作流程

11. Promise的API—构造函数—then—catch

  1. Promise(excutor){}
  2. Promise.prototype.then
  3. Promoise.prototype.catch
  4. Promise.resolve
    // 如果传入的参数为 非Promise 类型的对象,则返回的结果为成功promise对象
    // 如果传入的参数为 Promise 对象,则参数的结果决定了 resolve 的结果
    let p1 = Promise.resolve(521);
    let p2 = Promise((resolve, reject) => {
        reject('error')
    })
    console.log(p1);
    console.log(p2);
    p2.catch(reason => {
        console.log(reason)
    })

     

  5.  Promise.reject

    // 传入什么,失败的结果就是什么
    let p = Promise.reject(521);
    let p2 = Promise.reject('hello world');
    let p3 = Promise.reiect(Promise(resolve, reject) => {
        resolve('ok')
    })
    console.log(p3)

     

  6. Promise.all:(promise) => {}  promise包含n个promise的数组

    说明:返回一个新的promise,只有所有的promise都成功才成功,只要有一个失败了就直接失败;成功返回每一个成功promise的成功的结果组成的数组,失败返回失败的那个promise对象失败的结果。

    let p1 = new Promise((resolve, reject) => {
        resolve('OK')
    });
    let p2 = new Promise.resolve('Yes');
    // let p2 = new Promise.reject('NO');
    let p3 = new Promise.resolve('Success');
    
    const result = Promise.all([p1, p2, p3]);
    
    console.log(result);

     

  7. Promise.race:(promise) => {}  promise包含n个promise的数组        说明:返回一个新的promise,第一个完成的promise的结果状态就是最终的结果状态

    let p1 = new Promise((resolve, reject) => {
        setTimeout(() => {
            resolve('OK')
        }, 1000)
    });
    let p2 = new Promise.resolve('Yes');
    // let p2 = new Promise.reject('NO');
    let p3 = new Promise.resolve('Success');
    
    const result = Promise.race([p1, p2, p3]);
    
    console.log(result);

12. Promise关键问题

  1. Promise对象状态改变的方式
    let p = new Promise((resolve, reject) => {
        // 1.resolve 函数
        // resolve('ok');    // pending    =>   fullfilled / resolved
        // 2.reject 函数
        // reject('error');    // pending    =>    rejected
        // 3.抛出错误
        // throw '出问题了';
    });
    console.log(p);
  2. Promise指定多个成功/失败回调函数,都会调用吗?(当promise改变为对应状态时都会调用)
    let p = new Promise((resolve, reject) => {
        // 有改变对应状态的话就下面两个都会调用,没有改变状态就不会调用
        resolve('ok')
    });
    p.then(value => {
        console.log('ok');
    });
    p.then(value => {
        alert('ok')
    })
  3. 改变promise状态和指定回调函数谁先谁后?
    let p = new Promise((resolve, reject) => {
        // setTimeout(() => {
            resolve('ok')
        // })
    });
    p.then(value => {
        console.log(value)
    })

    (1)都有可能,正常情况下是先指定回调再改变状态,但也可以先改变状态再指定回调

         (2)如何先改变状态再指定回调?

                  ① 在执行器直接调用 resolve() / reject()

                  ② 延迟更长时间才调用 then()

            (3) 什么时候才能得到数据?

                  ① 如果先指定的回调,那当状态发生改变时,回调函数就会调用,得到数据

                  ② 如果先改变的状态,那当指定回调时,回调函数就会调用,得到数据

  1. promise.then()返回的新promise的结果状态由什么决定?
    let p = new Promise((resolve, reject) => {
        resolve('ok')
    });
    let result = p.then(value => {
        // console.log(value)
        // 1.抛出错误
        // throw ('出了问题');
        // 2.返回结果是非Promise类型的对象
        // return 521;
        // 3.返回结果是Promise对象
        return new Promise((resolve, reject) => {
            // resolve('success');
            reject('error');
        });
    }, reason => {
        console.warn(reason)
    });

     

    (1)简单表述:由then()指定的回调函数执行的结果决定

    (2)详细表达:

             ① 如果抛出异常,新promise变为rejected, reason为抛出的异常

             ② 如果返回的是非promise的任意值,新promise变为resolved,value为返回的值

             ③ 如果返回的是另一个新promise,此promise的结果就会成为新promise的结果

  1. promise如何串连多个操作任务?
    let p = new Promise((resolve, reject) => {
        setTimeout(()=>{
            resolve('ok');
        }, 1000)
    });
    p.then(value => {
        return new Promise((resolve, reject) => {
            resolve('success')
        });
    }).then(value => {
        console.log(value)    // success
    }).then(value  => {
        console.log(value)    // undefined
    })

     

(1)promise的then()返回一个新的promise,可以看成then()的链式调用

(2)通过then的链式调用串连多个同步/异步任务

  1. 中断promise链?

    let p = new Promise((resolve, reject) => {
        setTimeout(()=>{
            resolve('ok');
            // reject('err')
        }, 1000)
    });
    p.then(value => {
        // console.log(111);
        // 链式穿透
        // throw 'ERROR'
        // 中断 有且只有一个方式
        return new Promise(() => {});
    }).then(value => {
        console.log(222);
    }).then(value  => {
        console.log(333);
    }).catch(reason => {
        console.log(reason);
    });

     

(1)当使用promise的then链式调用时,在中间中断,不再调用后面的回调函数

(2)办法:在回调函数中返回一个pending状态的promise对象


我真的真的真的不会弄这个有序列表,离谱!呸!


13. Promise自定义封装

// 实例化对象
let p = new Promise((resolve, reject) => {
    // 同步任务下then返回结果
    // resolve('ok')
    // 异步任务下then的返回结果
    setTimeout(() => {
        resolve('ok');
    }, 1000)
    // reject('error')
    // 抛出异常
    // throw 'error';
    // 异步任务——then方法实现
    // setTimeout(() => {
        // resolve('ok');
    // }, 1000)
})

// console.log(p);

// p.then(value => {
    // console.log(value);
// }, reason => {
    // console.warn(reason);
// })

// 同步任务then返回结果
// const res = p.then(value => {
    // console.log(value);
    // return 'hello Promise';
    // return new Promise((resolve, reject) => {
        // resolve('success');
        // reject('oh no');
    // })
    // 抛出异常
    // throw "FAIL";
// }, reason => {
    // console.warn(reason);
// })
// console.log(res)

// 异步任务下then的返回结果
const res = p.then(value => {
    console.log(value);
}, reason => {
    console.warn(reason);
})
console.log(res);

// 指定多个回调的实现
// p.then(value => {
    // console.log('ok');
// }, reason => {
    // console.warn('no');
// })

// p.then(value => {
    // alert('ok');
// }, reason => {
    // alert('no')
// })

let p1 = new Promise((resolve, reject) => {
    setTimeout(() => {
        resolve('OK');
    }, 1000)
})
let p2 = Promise.resolve('Success');
let p3 = Promise.resolve('Oh Yeah');

// 调用all方法
// let result = Promise.all([p1, p2, p3]);

// 调用race方法
// let result = Promise.race([p1, p2, p3]);

console.log(result);

// 回调函数异步执行
let p1 = new Promise((resolve, reject) => {
    resolve('OK');
});
p1.then(value => {
    console.log(value);
})
// class版本封装
class Promise{

    // 构造方法
    constructor(executor){
        // 添加属性
        this.PromiseState = 'pending';
        this.PromiseResult = null;
        // 指定多个回调时,使每个回调函数都能被执行
        this.callbacks = [];

        // 保存实例对象的this值 self _this that
        const self = this;
        // resolve函数
        function resolve(data){
            // 判断状态,使Promise对象状态只能修改一次
            if(self.PromiseState !== 'pending') return;
            // 1.修改对象的状态(promiseState)
            self.PromiseState = 'fulfilled';
            // 2.修改对象结果值(promiseResult)
            self.PromiseResult = data;
            // 异步时,判断调用then方法时,有没有保存对应的回调函数。调用成功的回调函数
            // 遍历回调函数数组,执行所有被保存的失败的回调函数
            setTimeout(() => {
                self.callbacks.forEach(item => {
                    item.onResolved(data);
                })
            });
        }
        // reject函数
        function reject(data){
            // 判断状态,使Promise对象状态只能修改一次
            if(self.PromiseState !== 'pending') return;
            // 1.修改对象的状态(promiseState)
            self.PromiseState = 'rejected';
            // 2.修改对象结果值(promiseResult)
            self.PromiseResult = data;
            // 异步时,判断调用then方法时,有没有保存对应的回调函数。调用失败的回调函数
            // 遍历回调函数数组,执行所有被保存的成功的回调函数
            setTimeout(() => {
                self.callbacks.forEach(item => {
                    item.onRejected(data);
                })
            });
        }
        try{
            // 同步调用【执行器函数】
            executor(resolve, reject);
        }catch(e){
            // 抛出异常时,修改promise对象状态为【失败】
            reject(e);
        }
    }

    // then方法封装
    then(onResolved, onRejected){
        const self = this;
        // 判断回调函数参数
        if(typeof onRejected !== 'function'){
            onRejected = reason => {
                throw reason;
            }
        }
        if(typeof onResolved !== 'function'){
            onResolved = value => value;
        }
        return new Promise((resolve, reject) => {
            // 封装函数
            function callback(type){
                try {
                    // 获取回调函数的执行结果
                    let result = type(self.PromiseResult)
                    // 判断
                    if(result instanceof Promise){
                        // 如果是Promise类型的对象
                        result.then(v => {
                            resolve(v);
                        }, r => {
                            reject(r);
                        })
                    }else {
                        // 结果的对象状态为【成功/失败】
                        resolve(result);
                    }
                }catch(e) {
                    reject(e);
                }
            }

            // 同步时,在调用then方法时,Promise状态已经改变了,可以直接调用回调函数
            // 调用回调函数
            if(this.PromiseState === 'fulfilled'){
                setTimeout(() => {
                    callback(onResolved);
                });
            }
            if(this.PromiseState === 'rejected'){
                setTimeout(() => {
                    callback(onRejected);
                });
            }
            // 异步时,调用then方法时,Promise的状态还没有改变,将then方法调用的回调函数保存起来,等异步方法执行结束后,也就是Promise的状态改变后,让resolve()方法和reject()方法调用该回调函数
            if(this.PromiseState === 'pending'){
                // 保存回调函数
                // 防止then方法指定了多个回调时,只保存最后一个回调函数。所以通过push的方法,将指定的多个回调函数全部保存到callbacks数组中
                this.callbacks.push({
                    onResolved: function(){
                        callback(onResolved);
                    },
                    onRejected: function(){
                        callback(onRejected);
                    }
                });
            }
        })
    }

    // catch方法封装
    catch(onRejected){
        return this.then(undefined, onRejected);
    }

    // resolve方法封装
    static resolve(value){
        // 返回promise对象
        return new Promise((resolve, reject) => {
            if(value instanceof Promise){
                value.then(v => {
                    resolve(v);
                }, r => {
                    reject(r);
                })
            } else {
                // 状态设置为成功
                resolve(value);
            }
        })
    }
    
    // reject方法封装
    static reject(reason){
        return new Promise((resolve, reject) => {
            reject(reason);
        })
    }

    // all方法封装
    static all(promises){
        // 返回结果
        return new Promise((resolve, reject) => {
            // 声明变量
            let count = 0;
            // 存放成功结果的数组
            let arr = [];
            // 遍历
            for(let i=0;i<promises.length;i++){
                //
                promises[i].then(v => {
                    // 得知对象的状态是成功
                    // 每个promise对象都成功
                    count++;
                    // 将当前promise对象成功的结果,存入到数组中
                    arr[i] = v;
                    // 判断
                    if(count === promises.length){
                        // 修改状态
                        resolve(arr);
                    }
                }, r => {
                    reject(r);
                })
            }
        })
    }

    // race方法封装
    static race(promises){
        return new Promise((resolve, reject) => {
            for(let i=0;i<promise.length;i++){
                promises[i].then(v => {
                    // 修改返回对象的状态为【成功】
                    resolve(v);
                }, r => {
                    // 修改返回对象的状态为【失败】
                    reject(r);
                })
            }
        })
    }

}

绕来绕去的,头都要炸掉了!!!!!!!!


14. async函数

  • async function main(){
        // 1.如果返回值是一个非Promise类型的数据,结果就是一个成功状态的promise对象,而且你返回的数据就是成功的结果值
        return 521;
        // 2.如果返回值是一个Promise类型的数据,该promise返回的状态和结果就是main函数的状态和结果
        return new Promise((resolve, reject) => {
            resolve('OK')
        })
        // 3.抛出异常,结果就是一个失败的Promise对象,而且抛出的结果就是失败的结果值
        throw 'oh no'
    }
    
    let result = main();
    
    console.log(result);

15. await表达式

  1. await右侧的表达式一般为promise对象,但也可以是其他的值
  2. 如果表达式是promise对象,await返回的是promise成功的值
  3. 如果表达式是其他值,直接将此值作为await的返回值

16. 注意

  1. await必须写在async函数中,但async函数中可以没有await
  2. 如果await的promise失败了,就会抛出异常,需要通过try...catch捕获处理

17. async与await结合

-

18. async与await结合发生ajax请求


农历27号啦!快过年了,无心上班,干脆直接截图了,其实后面都没咋听了哈哈哈哈。明天就回家了,过年给它补回来!


 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,关于 jQuery 的事件,我可以和你分享一些学习笔记。 1. 绑定事件 在 jQuery 中,我们可以通过以下方式来绑定事件: ``` $(selector).event(function(){ // 事件处理程序 }) ``` 其中,`selector` 表示要绑定事件的元素,`event` 表示要绑定的事件类型,比如 `click`、`mouseover` 等等。事件处理程序则是在事件触发时要执行的代码块。 2. 多个事件绑定 我们可以通过 `on()` 方法来同时绑定多个事件: ``` $(selector).on({ event1: function(){ // 事件处理程序1 }, event2: function(){ // 事件处理程序2 } }) ``` 这样,当 `event1` 或 `event2` 中任意一个事件触发时,对应的处理程序都会被执行。 3. 解除事件 如果需要解除某个元素的事件处理程序,可以使用 `off()` 方法: ``` $(selector).off(event); ``` 其中,`event` 表示要解除的事件类型。如果不指定事件类型,则会解除该元素上所有的事件处理程序。 4. 事件委托 在 jQuery 中,我们可以使用事件委托来提高性能。事件委托是指将事件绑定到父元素上,而不是绑定到子元素上,然后通过事件冒泡来判断是哪个子元素触发了该事件。这样,当子元素数量较多时,只需要绑定一次事件,就可以监听到所有子元素的事件。 ``` $(selector).on(event, childSelector, function(){ // 事件处理程序 }) ``` 其中,`selector` 表示父元素,`event` 表示要绑定的事件类型,`childSelector` 表示要委托的子元素的选择器,事件处理程序则是在子元素触发事件时要执行的代码块。 以上是 jQuery 中事件的一些基本操作,希望对你有所帮助。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值