学习Async和Promise

学习Async和Promise
  • promise
    • 主要用于异步计算

    • 使异步操作队列化,按照期望得顺序执行,返回符合预期得结果

    • 可以在对象之间传递和操作promise,帮助我们处理队列

    • 两个特点

      • 对象的状态不受外界影响。Promise 对象代表一个异步操作,有三种状态:Pending(进行中)、Resolved(已完成,又称 Fulfilled)和 Rejected(已失败)。只有异步操作的结果,可以决定当前是哪一种状态,任何其他操作都无法改变这个状态。
      • 一旦状态改变,就不会再变,任何时候都可以得到这个结果。
    • easy-example

      	new Promise(resolve => {
      	setTimeout(() => {
      		resolve('hello');
         	}, 2000);
      	}).then(res => {
      	console.log(res);
      },)
      
      
  • .then()

    • 接收两个函数作为参数,分别代表 fulfilled (成功)和rejected(失败)
    • .then()返回一个新的Promise实例,所以它可以链式调用
    • 当前的Promise状态改变时,.then() 根据其最终状态,选择特
      定的状态响应函数执行
    • 如果返回新的Promise,那么下一级 .then 会在新的promise状
      态改变之后执行
    • 状态响应函数可以返回新的promise, 或其他值,不返回值也
      可以,我们可以认为它返回了一个null
    • 如果返回其他任何值,则会立即执行下一级 .then()
  • 错误处理

    • 第一种: reject(‘错误信息’) .then(() => {}, () => {错误处理逻辑})
    new Promise((resolve, reject) => {
    setTimeout(() => {
    reject('bye');
    	}, 2000)
    })
     .then((val) => {
      console.log(val)
    }, (err) => {
    console.log('Error:' + err);
    })
    
    • 第二种
    	new Promise((resolve) => {
    	setTimeout(() => {
    	throw new Error('bye');
    	 }, 2000)
    	 }).then((value) => {
    	 console.log(value);
    	}).catch(error => {
    	 console.log('Error', error);
    	 })
    
    • 多个then嵌套
    new Promise(resolve => {
    console.log('step 1');
    setTimeout(() => {
        resolve('100');
    }, 1000)
    }).then(value => { // value = 100
    return new Promise(resolve => {
        console.log('step-1-1');
        setTimeout(() => {
            resolve('110');
        }, 1000)
    })
    }).then(value => { //value = 110
    console.log('step-1-2');
    return value;
    }).then(value => { // value = 110
    console.log('step-1-3');
    return value; // value = 110
    }).then(value => {
    console.log(value); // value = 110
    console.log('step 2');
    })
    
    • 运行结果
    • 在这里插入图片描述
    • catch() + then()错误处理
      • 第一种
        console.log('here we go...')
    new Promise(resolve => {
        setTimeout(() => {
            resolve();
        }, 2000)
    })
        .then(() => {
            console.log('start');
            throw new Error('test error');
        })
        .catch(err => {
            console.log('I catch:', err);
        })
        .then(() => {
            console.log('arrive here');
        })
        .then(() => {
            console.log('...and here');
        })
        .catch(err => {
            console.log('No, I catch:', err)
        })
    
    • 运行结果
    • 在这里插入图片描述
    • 第二种
       console.log('heoe we go..')
    new Promise(resolve => {
        setTimeout(() => {
            resolve();
        }, 2000)
    })
        .then(() => {
            console.log('start');
            throw new Error('test error');
        })
        .catch(err => {
            console.log('1 catch: ', err);
            throw new Error('another error');
        })
        .then(() => {
            console.log('arrlve here');
        })
        .then(() => {
            console.log('...and here');
        })
        .catch(err => {
            console.log('No, I catch', err)
        })
    
    • 运行结果
    • 在这里插入图片描述
  • 结论: 抛出错误变成rejected状态,catch也会返回一个promise实例,并且时resolved状态。

  • Promise.all () 批量执行

    • Promise.all([p1,p2,p3])用于将多个promise实例,包装成一个新的Promise实例,返回得实例就是普通得Promise它接收一个数组作为参数,可以不是数组,但必须具有 Iterator接口,数组里面可以是Promise对象,也可以是其他值,所有子Promise都完成,该Promise完成,返回值是全部值得数组,有任何一个失败,该Promise失败,返回值是第一个失败得子Promise结果

         function cutUp() {
        console.log('开始切菜');
        var p = new Promise(function (resolve, reject) {
            // 做一些异步操作
            setTimeout(function () {
                console.log('切菜完毕');
            }, 1000)
        })
        return p;
    }
    
    // 烧水
    function boil() {
        console.log('开始烧水');
        var p = new Promise(function (resolve, reject) {
            // 做一些异步操作
            setTimeout(function () {
                console.log('烧水完毕');
            }, 1000)
        })
        return p;
    }
    
    Promise.all([cutUp(), boil()])
        .then((result) => {
            console.log(result);
        })
    
    • 运行结果
    • 在这里插入图片描述
    • 注:all里面的promise实例会同时运行而不是按照顺序一个个运行
  • Promise.race ()

    • 与promise类似,区别在于它有任意一个完成就算完成,常用与异步操作和定时器放在一起,如果定时器先触发,就认为超时,告知用户。
  • promise.finally( ()=>{ } )

    • 用于指定不管 Promise 对象最后状态如何,都会执行的操作。
  • Promise.allSettled()

    • Promise.allSettled()方法接受一组 Promise 实例作为参
      数,包装成一个新的 Promise 实例。只有等到所有这些
      参数实例都返回结果,不管是fulfilled还是rejected,包装
      实例才会结束。
  • Promise.any()

    • Promise.any()方法接受一组 Promise 实例作为参
      数,包装成一个新的 Promise 实例。只要参数实例
      有一个变成fulfilled状态,包装实例就会变成
      fulfilled状态;如果所有参数实例都变成rejected状
      态,包装实例就会变成rejected状态//还只是一个提案用不了
  • Promise.resolve()

    将现有对象转为 Promise 对象

    • 1.参数是一个 Promise 实例:直接返回一个promise实例不改变
    • 2.参数是一个thenable对象
    let thenable = {
    then: function(resolve, reject) {
      resolve(42);
    }
    };
    
    • 3.参数不是具有then方法的对象,或根本就不是对象
    let p1 = Promise.resolve(thenable);
    p1.then(function(value) {
    console.log(value);  // 42
    });
    
    
    • 4.不带有任何参数
    const p = Promise.resolve('Hello');
    p.then(function (s){
    console.log(s)
    });
    
  • Promise.reject(reason)

    • Promise.reject(reason)方法也会返回一个新的 Promise 实例,该实例的状态为rejected。也就和resolve一样的。只不过这个是错误处理。
    • 用于处理不知道函数是异步还是同步的时候,让函数按照原来的顺序执行 。
     const f = () => console.log('now');
     Promise.resolve().then(f);
     console.log('next');            //但是还是提案 用不了,用了会说没有定义
    
     const f = () => console.log('now');
    (
    () => new Promise(
    resolve => resolve(f())
    )
    )();						//现在可以利用new一个promise时候就会执行的特点来执行try功能
    console.log('next');    
    
  • async 函数

async函数完全可以看作多个异步操作,包装成的一个 Promise 对象,而await命令就是内部then指令的语法糖。

  • 基本语法
    • async函数返回一个 Promise 对象,可以使用then方法添加回调函数。当函数执行的时候,一旦遇到await就会先返回,等到异步操作完成,再接着执行函数体内后面的语句
    function timeout(ms) {
    return new Promise((resolve) => {
      setTimeout(resolve, ms);
    });
    }
    async function asyncPrint(value, ms) {
    await timeout(ms);
    console.log(value);
    }
    asyncPrint('hello world', 50);
    
    在这里插入图片描述
    • async 函数有多种使用形式。
    // 函数表达式
    const foo = async function () {};
    
    // 对象的方法
    let obj = { async foo() {} };
    obj.foo().then(...)
    
    // Class 的方法
    class Storage {
    constructor() {
    this.cachePromise = caches.open('avatars');
    }
    
    async getAvatar(name) {
    const cache = await this.cachePromise;
    return cache.match(`/avatars/${name}.jpg`);
    }
    }
    const storage = new Storage();
    storage.getAvatar('jake').then(…);
    
    // 箭头函数
    const foo = async () => {};
    
  • async函数返回一个 Promise 对象
    • async函数内部return语句返回的值,会成为then方法回调函数的参数
    async function f() {
    return 'hello world';
    }
    
    f().then(v => console.log(v))
    
    • async函数内部抛出错误,会导致返回的 Promise 对象变为reject状态。抛出的错误对象会被catch方法回调函数接收到。
    async function f() {
    await Promise.reject('出错了');
    }
    
    f()
    .then(v => console.log(v))
    .catch(e => console.log(e))
    // 出错了
    
    • async函数返回的 Promise 对象,必须等到内部所有await命令后面的 Promise 对象执行完,才会发生状态改变,除非遇到return语句或者抛出错误。也就是说,只有async函数内部的异步操作执行完,才会执行then方法指定的回调函数。
  • Await命令
    • 正常情况下,await命令后面是一个 Promise 对象,返回该对象的结果。如果不是 Promise 对象,就直接返回对应的值。
    • await命令后面是一个thenable对象(即定义then方法的对象),那么await会将其等同于 Promise 对象。
    • 任何一个await语句后面的 Promise 对象变为reject状态,那么整
      个async函数都会中断执行。
      async function f() {
      await Promise.reject('出错了');
      await Promise.resolve(console.log(1)); // 不会执行
      }
      f();
      
      • 若不想中断两种方法
        async function f() {
        try {
          await Promise.reject('出错了');
        } catch(e) {
        }
        return await Promise.resolve('hello world');
        }
          f()
        .then(v => console.log(v))        //
        
        async function f() {
        await Promise.reject('出错了')
        .catch(e => console.log(e));
        return await Promise.resolve('hello world');
        }  
        f()
        .then(v => console.log(v))
        
        • 注意点
          • await命令后面的Promise对象,运行结果可能是rejected,所以最好把await命令放在try…catch代码块中
          • 多个await命令后面的异步操作,如果不存在继发关系,最好让它们同时触发。
          • await命令只能用在async函数之中,如果用在普通函数,就会报错
          • async 函数可以保留运行堆栈
            const a = () => {
            b().then(() => c());
            };        //执行函数b的时候,a已经执行完了,错误栈就只有b或者c
            const a = async () => {
            await b();
            c();		//执行函数b的时候,a正在执行,所以错误栈就有a,b,c。
            };
            
    • 顶层await
      • 允许在模块的顶层独立使用await命令。这个提案的目的,是借用await解决模块异步加载的问题 //依然只是一个提案
      • 主要用在数据库的读取,import方法,让他们这些顶层同时执行。交出代码的执行权给其他的模块加载,等异步操作完成后,再拿回执行权,然后再继续向下执行。
      // import() 方法加载
      const strings = await import(`/i18n/${navigator.language}`);
      // 数据库操作
      const connection = await dbConnector();
      // 依赖回滚
      let jQuery;
      try {
        jQuery = await import('https://cdn-a.com/jQuery');
      } catch {
        jQuery = await import('https://cdn-b.com/jQuery');
      }
      
  • 总结一下:promise就是把原来复杂的回调函数简化了一哈,让函数看起来更加的容易读,方便维护,async和await就是一对,async可以来修饰函数,方法让他们成为一个promise实例。await是来执行那些promise函数的时候修饰用的。async和await就是promise的进阶版。
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值