zoukankan      html  css  js  c++  java
  • Promise对象深入理解

     目录

    基本用法

    返回另一个 Promise 实例

    Promise.prototypeof.then 

    Promise.prototype.catch 

    Promise.prototype.finally() 

    Promise.resolve()

    Promsie.reject()

    Promise 的执行顺序

    基本用法

    Promise 对象是一个构造函数,下面的例子生成一个 promise 对象

    const promise = new Promise((resolve, reject)=>{
        if(true){
            resolve('异步操作成功了');
        }else{
            rejecte('异步操作失败了');
        }
    })

    Promise 构造函数接受一个函数为参数,这个函数还接受两个参数,这两个参数都是函数

    第一个函数用于异步成功,并将异步成功的结果以参数的形式传递出去,同时 promise 的状态改为 resolved

    第二个函数用于异步失败,并将异步失败的结果以参数的形式传递出去,同时 promise 的状态改为 rejected

    返回另一个 Promise 实例

    通常情况 reject 函数返回的是异步错误信息,resolve 函数返回的是正常的理想值,而这个值也可以是另一个 Promise 实例,

    如果返回的是另一个 Promise 的实例,那么这个实例将决定当前 Promise 实例的状态,自己本来的状态将失效

    const p1 = new Promise(function (resolve, reject) {
      // ...
    });
    
    const p2 = new Promise(function (resolve, reject) {
      // ...
      setTimeout( () => {resolve(p1),2000 }); // p1 的状态将决定 p2 的状态,而不是等到 2s 后
    })

     

    Promise.prototypeof.then 

    then 方法接受两个函数为参数,通常需要将 Promise 异步的结果作为参数传进去

    第一个函数是 异步成功时(resolved)执行

    第一个函数是 异步失败时(resolved)执行(可以不传该函数,改用 catch 方法监听异步的失败)

    promise.then((res)=>{
        console.log(res);
    }, (rej)=>{
        cnosole.log(rej);
    })

    then 方法会将新的 Promise 对象,因此可以链式调用。如果有返回值,那么返回值将作为参数传给新的 Promise 对象

    promise.then((res)=>{
        console.log(res);
        return 'newPromise';
    }, (rej)=>{
        cnosole.log(rej);
    }).then((res => {
        console.log(res);
    })

    如果返回的新的 promise对象存在异步操作,例如返回一个 新的 Promise 实例对象,那么后面的 then 方法会等到这个promise状态发生改变时才执行

    Promise.prototype.catch 

    上面有说到 then 方法接收两个函数为参数,分别是成功和失败时执行的,并且建议失败的函数改用 catch 方法

    catch 可以实现 then 方法第二个参数的功能,但是它可以上代码跟直观

    let a = 1;
    let promise = new Promise(function(resolve, reject){
        if(a==10){
            resolve('成功');
        }else{
            reject('失败');
        }
    });
    
    promise.then(res=>{
        console.log(res);
    }).catch(err=>{  
        console.log(err);
    })

    promise 对象的错误具有“冒泡”性质,会一直向后传递,直到被捕获为止。也就是说,错误总是会被下一个catch语句捕获。

     

     Promise.prototype.finally() 

    finally 方法用于指定 不管 Promise 对象最后状态如何,都会执行的操作。

    promise
    .finally(() => {});

    Promise.resolve()

    将现有对象转换为 promise 对象,分下面四种情况

    1. 如果参数是 Promise 实例,那么 promise.resolve 将不做任何修改、原封不动地返回这个实例。

    2. 如果参数是一个 thenable 对象。thenable 对象指的是具有 then 方法的对象,比如下面这个对象。Promise.resolve 方法会将这个对象转为 Promise 对象,然后就立即执行thenable对象的then方法。

    let thenable = {
      then: function(resolve, reject) {
        resolve(42);
      }
    };
    
    let p1 = Promise.resolve(thenable);
    p1.then(function(value) {
      console.log(value);  // 42
    });

    3. 如果参数是一个原始值,或者是一个不具有then方法的对象,则 Promise.resolve 方法返回一个新的 Promise 对象,状态为 resolved。下面代码生成一个新的 Promise 对象的实例p。由于字符串 Hello 不属于异步操作(判断方法是字符串对象不具有 then 方法),返回 Promise 实例的状态从一生成就是 resolved,所以回调函数会立即执行。Promise.resolve 方法的参数,会同时传给回调函数。

    const p = Promise.resolve('Hello');
    
    p.then(function (s){
      console.log(s)
    });
    // Hello

    4. Promise.resolve 方法允许调用时不带参数,直接返回一个 resolved 状态的 Promise 对象。需要注意的是,立即 resolve() 的 Promise 对象,是在本轮“事件循环”(event loop)的结束时执行,而不是在下一轮“事件循环”的开始时

    setTimeout(function () {
      console.log('three');
    }, 0); // 下一轮“事件循环”开始时执行,
    
    Promise.resolve().then(function () {
      console.log('two');
    }); // 在本轮“事件循环”结束时执行
    
    console.log('one');
    
    // one
    // two
    // three

     

    Promsie.reject()

    同样也是将现有对象转换为 promise 对象,只不过 promise 对象的状态是 rejected

    const p = Promise.reject('出错了');
     p.catch(rej => console.log(rej))

    Promise 的执行顺序

    Promise 构造函数本身是同步执行的

    then 方法会被放到微任务(microtask)队列中

    setTimeout 定时器会放到宏任务(macrotask)队列中

    当同步任务执行完后,微任务队列中的任务依次进入主线程执行,当微任务队列为空以后,宏任务队列中的任务依次进入主线执行

    setTimeout(() => {
        console.log(0);
    },0)
    
    new Promise(resolve => {
        resolve(1);
        Promise.resolve().then(t => {
            console.log(2);
        })
        console.log(3);
    }).then(t => {
    console.log(t);
    })
    
    console.log(4);
    // 3
    // 4
    // 2
    // 1
    // 0

    现在分析上面的代码

     1. 遇到定时器,将它放到宏任务队列中(这是第一个宏任务)

     2. 同步执行构造函数

     3. 在构造函数中遇到一个 then 方法,将他放到微任务队列中(这是第一个微任务)

     4. console.log(3) 执行,打印出 3

     5. 遇到第二个 then 方法,将他放到微任务队列的末尾

     6. console.log(4) 执行,打印出 4

     7. 读取微任务队列中的任务,依次打印出 2  1

     8. 读取宏任务队列中的任务,打印出 0

  • 相关阅读:
    58到家数据库30条军规解读
    mysql那些事(6) WHERE条件 字符串的引号
    按照ID倒序查出某个字段不重复的集合
    mysql那些事(5)建表存储引擎的选择
    mysql那些事(4)建库建表编码的选择
    mysql那些事(3)小数如何存储
    mysql那些事(2)时间类型数据如何存储
    Failed to install apk on device timeout
    daemon not running. starting it now on port 5037 ADB server didn't ACK
    webview
  • 原文地址:https://www.cnblogs.com/wangjie-nf/p/10974040.html
Copyright © 2011-2022 走看看