• Promise相关


    Promise相关

    关于异步:

    出现背景:

    • 由于JS是单线程语言,因此所有网络操作、浏览器事件都必须是异步执行的。

    异步解决方案:

    方案一:回调函数方式(注册-执行异步任务-触发回调函数)
    原理:
    • 浏览器解释执行js代码过程中,遇到异步任务,首先在系统中挂起(异步队列中注册回调函数),当异步任务(eg:I/O,网络请求等操作完成之后),通过触发回调函数的方式完成整个异步操作。
    异步的问题:
    • 传统采用回调函数处理异步任务的方式可以处理问题,但可能进入回调地狱,剥夺return的权利
    • 回调方式,代码嵌套层次深,易读性差,且不易维护
    场景:
    • setTimeOut
    • ajax请求

    方案二:Promise方式

    概念:

    • Promise是一个对象:承诺将来会执行的对象(代表异步操作最终成功或者失败)
    • promise作为队列最为重要的特性,我们在任何一个地方生成了一个promise队列之后,我们可以把他作为一个变量传递到其他地方。
    • 三种状态:pending、fulfilled、rejected
    • 两类函数:resolve(),将pending状态变为fulfilled状态,rejecte(),将pending状态变为rejected状态
    • thenable对象:具有特定格式then属性的对象

    约定(与传统回调函数不同):

    • 本轮Event Loop完成之前,回调函数不会被调用
    • then函数总会被调用,即使它是异步操作完成之后才添加的
    • 多次调用then,可以添加多个回调函数,它们会按照插入顺序,一个接一个独立执行
    • ** 因此,Promise最直接的好处是链式调用

    问题场景:

    then方法中返回的不是Promise对象
    • 若返回为空,程序默认返回值为null
    • 若返回其他非Promise对象,程序直接进入下一级then方法中
    catch + then
    • catch只抓当前作用域的错误,过期不候
    • catch之后还可以继续执行then方法,但是跳过的方法将不再执行
    • 建议使用reject的方式抛出错误,而非new Error
    console.log('程序开始执行')
    new Promise((resolve)=>{
        setTimeout(()=>{
            resolve()
        },200)
    })
    .then(()=>{
        console.log('then_1开始执行')
        reject('then_1中执行了reject方法')
    })
    .then(()=>{
        console.log('then_2开始执行')
    })
    .catch((err)=>{
        console.log('I catch' + err)
    })
    .then(()=>{
        console.log('then_3开始执行')
    })
    .catch((err)=>{
        console.log('最终err未执行')
    })
    
    输出结果:
        程序开始执行
        then_1开始执行
        I catch then_1中执行了reject方法
        then_3开始执行
    

    方法:

    // 包装不支持Promise语法的函数
    new Promise()
    // 所有Promise任务执行完成才能执行then
    // Promise对象组成的数组作为参数
    Promise.all()
    // 只要有其中一项完成,即可执行then
    Promise.race()
    // 手动创建一个resolve的Promise
    Promise.resolve()
    // 手动创建一个reject的Promise
    Promise.reject()
    
    Promise.prototype.then()
    Promise.prototype.catch()
    Promise.prototype.finally()
    
    

    源码实现方式:

    const PENDING = 'pending'; //初始状态
    const FULFILLED = 'fulfilled'; // 成功状态
    const REJECTED = 'rejected'; // 成功
    function Promise(extutor){
      let self = this;
      self.status = PENDING; // 设置状态
      // 存放成功回调的数组
      self.onResolveCallbacks = [];
      // 存放失败回调的数组
      self.onRejectedCallbacks = [];
      function resolve(value){
        if(self.status === PENDING){
          self.status = FULFILLED;
          self.value = value;
          self.onResolveCallbacks.forEach(cb => cd(self.value))
        }
      } 
      function reject(reason){
        if(self.status === PENDING){
          self.status = REJECTED;
          self.value = reason;
          self.onRejectCallbacks.forEach(cb => cd(self.value))
        }
      } 
      try{
        excutor(resolve, reject)
      } catch(e) {
        reject(e)
      }
    }
    
  • 相关阅读:
    Web Api跨域访问配置及调用示例
    EasyUI datagrid 日期时间格式化
    bootstrap-table组合表头
    Tomcat version 7.0 only supports J2EE 1.2, 1.3, 1.4, and Java EE 5 and 6 Web mod
    Java 开发环境配置
    一台电脑上配置多个tomcat
    使用plsql Developer 连接远程服务器
    阿里云初识
    算法入门———冒泡排序
    算法入门———递归
  • 原文地址:https://www.cnblogs.com/nanhuaqiushui/p/11774274.html
Copyright © 2020-2023  润新知