学习ES6知识系列(二)| 8月更文挑战

356 阅读5分钟

前言🎃

Promises(期约)

我们一起定个约定image.png好不好,“等你瘦了,我就做你女朋友”,如果你失败了,那就。。。

之后我就在努力减肥。。。

src=http___m.xinhuanet.com_sd_2019-03_09_1124213542_15521156874341n.gif&refer=http___m.xinhuanet.gif

减肥成功image.png了😊: 我们一起去看美丽的风景 💕

减肥失败image.png了😔:没事的,我看到了你的努力,你做我男朋友好不好

logo (30).png

主要内容🎃

  • Promise与异步编程

前置知识

为什么出现异步编程?

js是建立在单线程事件循环的概念之上的。单线程意味着同一时刻只能执行一段代码。这是它的特点。所以它适用于操作dom树。

补充:事件循环(event loop )是 JS 引擎的一个内部处理线程,能监视代码的执行并管理作业队列。

但是也有一些其他情况,如果遇到代码A比较耗时的时候,我们需要一直等待,但是这样体验并不是我们想要的。

因为它不影响我下一段代码的执行.所以我们希望在等待的过程中,执行下一段代码B。这样我们就需要定一个期约。也就是约定,因为怕它过太长时间忘记。以后我要通过这个约定来办的事情。

let promise = new Promise(function(resolve, reject) {
console.log("Promise");
resolve();
});
// promise 就是一个约定(但是不知道结果是什么呢)
// 即使过了很多年,我也可以靠这个约定调用then方法,来办事情,
// 如果成功就这样办,如果失败就那样办。如果中间不在了(遇到错误),直接抛出错误
promise.then(function() {
console.log("Resolved.");
},function(){
console.log();
}).catch(error){
conole.log('error',error)
};

浏览器中自己也设置一些耗时的需要异步执行的

比如:定时器线程 http请求 页面渲染

补充知识点:

  1. 一个浏览器可以有多个进程

  2. 每一个tab页面都是一个进程,一个进程可以多个线程,包含js线程,渲染线程等

回顾以往的异步编程背景

第一种:事件模型

当我们写一个点击事件的时候,其实就是一个事件被触发,该事件的处理函数被加到一个作业队列的尾部。等待执行。

let button = document.getElementById("myBtn");
button.onclick = function(event) {
console.log("Clicked");
};

第二种: 回调模式

Node.js 使用了异步回调方式,错误优先的原则,同样是一个新的作业添加到作业队列的尾部。下面代码展示了回调模式。

readFile("example.txt", function(err, contents) {
// 新的作业
if (err) {
throw err;
}
console.log(contents);
});
console.log("Hi!");

第三种:解决回调地狱

下面介绍了Promise来解决这个问题,🤔其他方案还有吗?(可以评论区留言)

Promise与异步编程🎃

第一步:先简单实现一个Promise

let promise = new Promise(function(resolve, reject) {
  // 1
  console.log("Promise");
  resolve();
});
promise.then(function() {
  // 3 A
  console.log("Resolved.");
});
// 2
console.log("Hi!");
// Promise
// Hi
// Resolved

思路解析:

  1. promise执行器里先执行

  2. then()方法把要执行的函数A加到作业队列的尾部

  3. 执行打印语句log('Hi')

  4. 执行队列里的函数A

promise的生命周期

  1. 挂起状态:pending (这时不知道结果是什么)
  2. 知道结果后有两种: 已完成(fulfilled) 已拒绝(rejected)

promise的方法(不一一展开,可以自己查询使用方法)

  1. Promise.then()

  2. Promise.catch()

  3. Promise.resolve()

  4. Promise.reject()

以上的方法都可以单独执行,例如下面的这个例子

let promise = Promise.reject(42);
promise.catch(function(value) {
console.log(value); // 42
});

看一下Promise.all() 与 Promise.race()的测试,我们一起分析它们的不同之处

    let promise1 = new Promise(function(reslove,reject){
        setTimeout(function () {
            console.log('传过去3');
            reslove(3)
        },3000)
    });
    let promise2 = new Promise(function(reslove,reject){
        setTimeout(function () {
            console.log('传过去1');
            reslove(1)
        },2000)
    });
    // all测试
    Promise.all([promise1,promise2]).then(result=>{
        console.log('all的结果是',result);
    }).catch(error=>{
        console.log(error);
    });
    // race 测试
    Promise.race([promise1,promise2]).then(result=>{
        console.log('race的结果是',result);
    }).catch(error=>{
        console.log(error);
    });

image.png

上面结果显示,race方法返回的是1这一个值,all返回的是[3,1]两个值,但是两个都是先执行的promise2(因为耗时短),因此我们能想到:race返回最快执行的某一个结果,而all()方法会按照之前数组的顺序。

扩展思考🤔:对于返回错误,或抛出错误,它们是如何应对的呢?(欢迎评论留言)

promise在不同环境的错误处理

  1. 执行器错误
let promise = new Promise(function(resolve, reject) {
throw new Error("我要报错!");
});
promise.catch(function(error) {
console.log(error.message); // "我要报错!"
})

这种情况,在执行器处理中会捕捉错误,并抛出错误

  1. promise在Node.js 和浏览器中的拒绝处理

Promise 被 reject 且没有 reject 处理器的时候,会触发 unhandledrejection 事件;这可能发生在 window 下,但也可能发生在 Worker 中。 这对于调试回退错误处理非常有用。

let promise1;
process.on("unhandledRejection", function(reason, promise) {
console.log(reason.message); // "报错了!"
console.log(promise1 === promise); // true
});
promise1 = Promise.reject(new Error("报错了!"));
//报错了!
//true

这块,可以作为一个话题,欢迎在评论区讨论相关问题。

promise异步编程开发实践

利剑1🔪:利用好链式调用

前端调接口是否有这样的场景?

用接口1的结果作为参数请求接口2,用接口2的结果作为参数请求接口3

    new Promise(function(reslove,reject){
        // 操作:请求接口1
        // 返回接口1结果
         reslove('接口1结果')
    }).then(res=>{
        //拿到res(接口1的结果)
        // 操作:请求接口2
        // 返回接口2结果
        reslove('接口2结果')
    }).then(res1=>{
        //拿到res1(接口2的结果)
        // 操作:请求接口3
        // 返回接口3结果
        reslove('接口2结果')
    }).catch(error=>{
        console.log(error);
    })

利剑2🔪:利用好Promise.all()和Promise.race()

前端调接口是否有这样的场景?

**用接口1的结果和接口2的结果去请求接口3

    let promise1 = new Promise(function(reslove,reject){
          // 接口1请求 
          reslove('接口1结果')
    });
    let promise2 = new Promise(function(reslove,reject){
          // 接口2请求 
          reslove('接口2结果')
    });
    // 请求接口3
    Promise.all([promise1,promise2]).then(result=>{
        //接口1,2的结果是:result
        // 请求接口3
    }).catch(error=>{
        console.log(error);
    });

前端调接口是否有这样的场景?

**用接口1的结果或接口2的结果去请求接口3

    let promise1 = new Promise(function(reslove,reject){
          // 接口1请求 
          reslove('接口1结果')
    });
    let promise2 = new Promise(function(reslove,reject){
          // 接口2请求 
          reslove('接口2结果')
    });
    // 请求接口3
    Promise.race([promise1,promise2]).then(result=>{
        //接口1或2的结果是:result(获取请求最快的那个)
        // 请求接口3
    }).catch(error=>{
        console.log(error);
    });

手写简单的promise

今天就这样了,拜拜👋

在这里插入图片描述