ES6(四)用Promise封装一下IndexedDB

简介: IndexedDB 是一种底层 API,用于在客户端存储大量的结构化数据,它可以被网页脚本创建和操作。IndexedDB 允许储存大量数据,提供查找接口,还能建立索引,这些都是 LocalStorage 所不具备的。就数据库类型而言,IndexedDB 不属于关系型数据库(不支持 SQL 查询语句),更接近 NoSQL 数据库。其他的介绍就不搬运了,大家可以自行百度,后面有参考资料。

indexedDB



IndexedDB 是一种底层 API,用于在客户端存储大量的结构化数据,它可以被网页脚本创建和操作。 IndexedDB 允许储存大量数据,提供查找接口,还能建立索引,这些都是 LocalStorage 所不具备的。 就数据库类型而言,IndexedDB 不属于关系型数据库(不支持 SQL 查询语句),更接近 NoSQL 数据库。 其他的介绍就不搬运了,大家可以自行百度,后面有参考资料。


需求



我想更好的实现文档驱动的想法,发现需要实现前端存储的功能,于是打算采用 IndexedDB 来实现前端存储的功能。但是看了一下其操作方式比较繁琐,所以打算封装一下。


官网给了几个第三方的封装库,我也点过去看了看,结果没看懂。想了想还是自己动手丰衣足食吧。


关于重复制造轮子的想法:


  • 首先要有制造轮子能能力。


  • 自己造的轮子,操控性更好。


功能设计



按照官网的功能介绍,把功能整理了一下: 如图:


image.png


就是建库、增删改查那一套。看到有些第三方的封装库,可以实现支持sql语句方式的查询,真的很厉害。目前没有这种需求,好吧,能力有限实现不了。 总之,先满足自己的需求,以后在慢慢改进。


代码实现



还是简单粗暴,直接上代码吧,基础知识的介绍,网上有很多了,可以看后面的参考资料。官网介绍的也比较详细,还有中文版的。


配置文件


nf-indexedDB.config


const config = {
  dbName: 'dbTest',
  ver: 1,
  debug: true,
  objectStores: [ // 建库依据
    {
      objectStoreName: 'blog',
      index: [ // 索引 , unique 是否可以重复
        { name: 'groupId', unique: false }
      ]
    }
  ],
  objects: { // 初始化数据
    blog: [
      {
        id: 1,
        groupId: 1,
        title: '这是一个博客',
        addTime: '2020-10-15',
        introduction: '这是博客简介',
        concent: '这是博客的详细内容<br>第二行',
        viewCount: 1,
        agreeCount: 1
      },
      {
        id: 2,
        groupId: 2,
        title: '这是两个博客',
        addTime: '2020-10-15',
        introduction: '这是博客简介',
        concent: '这是博客的详细内容<br>第二行',
        viewCount: 10,
        agreeCount: 10
      }
    ]
  }
}
export default config
复制代码


  • dbName


指定数据库名称


  • ver


指定数据库版本


  • debug


指定是否要打印状态


  • objectStores


对象仓库的描述,库名、索引等。


  • objects


初始化数据,如果建库后需要添加默认数据的话,可以在这里设置。


这里的设置不太完善,有些小问题现在还没想好解决方法。以后想好了再改。


内部成员


/**
   * IndexedDB 数据库对象
   * 判断浏览器是否支持
   * */
  const myIndexedDB = window.indexedDB || window.webkitIndexedDB || window.mozIndexedDB || window.msIndexedDB
  if (!myIndexedDB) {
    console.log('你的浏览器不支持IndexedDB')
  }
  let _db // 内部保存的 indexed 数据库 的实例
  /**
  * 把vue的ref、reactive转换成原始对象
  */
  const _vueToObject = (vueObject) => {
    let _object = vueObject
    // 针对Vue3做的类型判断
    if (Vue.isRef(_object)) {
      // 如果是 vue 的 ref 类型,替换成 ref.value
      _object = _object.value
    }
    if (Vue.isReactive(_object)) {
      // 如果是 vue 的 reactive 类型,那么获取原型,否则会报错
      _object = Vue.toRaw(_object)
    }
    return _object
  }
复制代码


  • myIndexedDB


兼容浏览器的写法,适应不同的浏览器。


  • _db 内部的 IDBOpenDBRequest 用于检查是否打开数据库,以及数据库的相关操作。


  • _vueToObject


这是一个兼容Vue的对象转换函数。vue的reactive直接存入的话会报错,需要获取原型才能存入,我又不想每次保存的时候都多一步操作,所以就写了这个转换函数。 如果非vue3环境,可以直接返回参数,不影响其他功能。


建立对象库以及打开数据库


// ======== 数据库操作 ================
/**
  * 打开 indexedDB 数据库。
  * dbName:数据库名称;
  * version:数据库版本。
  * 可以不传值。
  */
  const dbOpen = (dbName, version) => {
    // 创建数据库,并且打开
    const name = config.dbName || dbName
    const ver = config.ver || version
    const dbRequest = myIndexedDB.open(name, ver)
    // 记录数据库版本是否变更
    let isChange = false
    /* 该域中的数据库myIndex */
    if (config.debug) {
      console.log('dbRequest - 打开indexedDb数据库:', dbRequest)
    }
    // 打开数据库的 promise
    const dbPromise = new Promise((resolve, reject) => {
      // 数据库打开成功的回调
      dbRequest.onsuccess = (event) => {
        // _db = event.target.result
        // 数据库成功打开后,记录数据库对象
        _db = dbRequest.result
        if (isChange) { // 如果变更,则设置初始数据
          setup().then(() => {
            resolve(_db)
          })
        } else {
          resolve(_db)
        }
      }
      dbRequest.onerror = (event) => {
        reject(event) // 返回参数
      }
    })
    // 创建表
    // 第一次打开成功后或者版本有变化自动执行以下事件,一般用于初始化数据库。
    dbRequest.onupgradeneeded = (event) => {
      isChange = true
      _db = event.target.result /* 数据库对象 */
      // 建立对象表
      for (let i = 0; i < config.objectStores.length; i++) {
        const object = config.objectStores[i]
        // 验证有没有,没有的话建立一个对象表
        if (!_db.objectStoreNames.contains(object.objectStoreName)) {
          const objectStore = _db.createObjectStore(object.objectStoreName, { keyPath: 'id' }) /* 创建person仓库(表) 主键 */
          // objectStore = _db.createObjectStore('person',{autoIncrement:true});/*自动创建主键*/
          // 建立索引
          for (let i = 0; i < object.index.length; i++) {
            const index = object.index[i]
            objectStore.createIndex(index.name, index.name, { unique: index.unique })
          }
          if (config.debug) {
            console.log('onupgradeneeded - 建立了一个新的对象仓库:', objectStore)
          }
        }
      }
    }
    // 返回 Promise 实例 —— 打开Indexed库
    return dbPromise
  }
复制代码


这段代码有点长,因为有两个功能,一个是打开数据库,一个是创建数据库。


indexedDB 的逻辑是这样的,在open数据库的时候判断本地有没有数据库,如果没有数据库则触发 onupgradeneeded 事件,创建数据库,然后打开数据库。 如果有数据库的话,判断版本号,如果高于本地数据库,那么也会触发 onupgradeneeded 事件。所以open和 onupgradeneeded 就联系在了一起。


初始化对象


/**
  * 设置初始数据
  */
  const setup = () => {
    // 定义一个 Promise 的实例
    const objectPromise = new Promise((resolve, reject) => {
      const arrStore = []
      // 遍历,获取表名集合,便于打开事务
      for (const key in config.objects) {
        arrStore.push(key)
      }
      const tranRequest = _db.transaction(arrStore, 'readwrite')
      // 遍历,添加数据(对象)
      for (const key in config.objects) {
        const objectArror = config.objects[key]
        const store = tranRequest.objectStore(key)
        // 清空数据
        store.clear().onsuccess = (event) => {
          // 遍历添加数据
          for (let i = 0; i < objectArror.length; i++) {
            store
              .add(objectArror[i])
              .onsuccess = (event) => {
                if (config.debug) {
                  console.log(`添加成功!key:${key}-i:${i}`)
                }
              }
          }
        }
      }
      // 遍历后统一返回
      tranRequest.oncomplete = (event) => {
        // tranRequest.commit()
        if (config.debug) {
          console.log('setup - oncomplete')
        }
        resolve()
      }
      tranRequest.onerror = (event) => {
        reject(event)
      }
    })
    return objectPromise
  }
复制代码


有的时候需要在建库之后设置一些初始化的数据,于是设计了这个函数。 setup会依据 nf-indexedDB.config 里的配置,把默认对象添加到数据库里面。


添加对象


基础的增删改查系列,不管是数据库还是对象库,都躲不开。


// ======== 增删改操作 ===================================
  /**
  * 添加对象。
  * storeName:对象仓库名;
  * object:要添加的对象
  */
  const addObject = (storeName, object) => {
    const _object = _vueToObject(object)
    // 定义一个 Promise 的实例
    const objectPromise = new Promise((resolve, reject) => {
      // 定义个函数,便于调用
      const _addObject = () => {
        const tranRequest = _db.transaction(storeName, 'readwrite')
        tranRequest
          .objectStore(storeName) // 获取store
          .add(_object) // 添加对象
          .onsuccess = (event) => { // 成功后的回调
            resolve(event.target.result) // 返回对象的ID
          }
        tranRequest.onerror = (event) => {
          reject(event)
        }
      }
      // 判断数据库是否打开
      if (typeof _db === 'undefined') {
        dbOpen().then(() => {
          _addObject()
        })
      } else {
        _addObject()
      }
    })
    return objectPromise
  }
复制代码


这么长的代码,只是实现了把一个对象填到数据库里的操作,可见原本的操作是多么的繁琐。


好吧,不开玩笑了,其实原本的想法是这样的,想要添加对象要这么写:


dbOpen().then(() =>{
  addObject('blog',{
    id: 3,
    groupId: 1,
    title: '这是三个博客',
    addTime: '2020-10-15',
    introduction: '这是博客简介',
    concent: '这是博客的详细内容<br>第二行',
    viewCount: 1,
    agreeCount: 1
  })
})
复制代码


就是说,每次操作的时候先开库,然后才能进行操作,但是想想这么做是不是有点麻烦? 能不能不管开不开库的,直接开鲁呢? 于是内部实现代码就变得复杂了一点。


修改对象


/**
  * 修改对象。
  * storeName:对象仓库名;
  * object:要修改的对象
  */
  const updateObject = (storeName, object) => {
    const _object = _vueToObject(object)
    // 定义一个 Promise 的实例
    const objectPromise = new Promise((resolve, reject) => {
      // 定义个函数,便于调用
      const _updateObject = () => {
        const tranRequest = _db.transaction(storeName, 'readwrite')
        // 按照id获取对象
        tranRequest
          .objectStore(storeName) // 获取store
          .get(_object.id) // 获取对象
          .onsuccess = (event) => { // 成功后的回调
            // 从仓库里提取对象,把修改值合并到对象里面。
            const newObject = { ...event.target.result, ..._object }
            // 修改数据
            tranRequest
              .objectStore(storeName) // 获取store
              .put(newObject) // 修改对象
              .onsuccess = (event) => { // 成功后的回调
                if (config.debug) {
                  console.log('updateObject -- onsuccess- event:', event)
                }
                resolve(event.target.result)
              }
          }
        tranRequest.onerror = (event) => {
          reject(event)
        }
      }
      // 判断数据库是否打开
      if (typeof _db === 'undefined') {
        dbOpen().then(() => {
          _updateObject()
        })
      } else {
        _updateObject()
      }
    })
    return objectPromise
  }
复制代码


修改对象,是新的对象覆盖掉原来的对象,一开始是想直接put,但是后来实践的时候发现,可能修改的时候只是修改其中的一部分属性,而不是全部属性,那么直接覆盖的话,岂不是造成参数不全的事情了吗?


于是只好先把对象拿出来,然后和新对象合并一下,然后再put回去,于是代码就又变得这么长了。


删除对象


/**
  * 依据id删除对象。
  * storeName:对象仓库名;
  * id:要删除的对象的key值,注意类型要准确。
  */
  const deleteObject = (storeName, id) => {
    // 定义一个 Promise 的实例
    const objectPromise = new Promise((resolve, reject) => {
      // 定义个函数,便于调用
      const _deleteObject = () => {
        const tranRequest = _db.transaction(storeName, 'readwrite')
        tranRequest
          .objectStore(storeName) // 获取store
          .delete(id) // 删除一个对象
          .onsuccess = (event) => { // 成功后的回调
            resolve(event.target.result)
          }
        tranRequest.onerror = (event) => {
          reject(event)
        }
      }
      // 判断数据库是否打开
      if (typeof _db === 'undefined') {
        dbOpen().then(() => {
          _deleteObject()
        })
      } else {
        _deleteObject()
      }
    })
    return objectPromise
  }
复制代码


其实吧删除对象,一个 delete 就可以了,但是还是要先判断一下是否打开数据库,于是代码还是短不了。


清空仓库里的对象


/**
  * 清空store里的所有对象。
  * storeName:对象仓库名;
  */
  const clearStore = (storeName) => {
    // 定义一个 Promise 的实例
    const objectPromise = new Promise((resolve, reject) => {
      // 定义个函数,便于调用
      const _clearStore = () => {
        const tranRequest = _db.transaction(storeName, 'readwrite')
        tranRequest
          .objectStore(storeName) // 获取store
          .clear() // 清空对象仓库里的对象
          .onsuccess = (event) => { // 成功后的回调
            resolve(event)
          }
        tranRequest.onerror = (event) => {
          reject(event)
        }
      }
      // 判断数据库是否打开
      if (typeof _db === 'undefined') {
        dbOpen().then(() => {
          _clearStore()
        })
      } else {
        _clearStore()
      }
    })
    return objectPromise
  }
复制代码


  • clear()


清空指定对象仓库里的所有对象,请谨慎操作。


删除对象仓库


/**
  * 删除整个store。
  * storeName:对象仓库名;
  */
  const deleteStore = (storeName) => {
    // 定义一个 Promise 的实例
    const objectPromise = new Promise((resolve, reject) => {
      // 定义个函数,便于调用
      const _deleteStore = () => {
        const tranRequest = _db.transaction(storeName, 'readwrite')
        tranRequest
          .objectStore(storeName) // 获取store
          .delete() // 清空对象仓库里的对象
          .onsuccess = (event) => { // 成功后的回调
            resolve(event)
          }
        tranRequest.onerror = (event) => {
          reject(event) // 失败后的回调
        }
      }
      // 判断数据库是否打开
      if (typeof _db === 'undefined') {
        dbOpen().then(() => {
          _deleteStore()
        })
      } else {
        _deleteStore()
      }
    })
    return objectPromise
  }
复制代码


这个就更厉害了,可以把对象仓库给删掉。更要谨慎。


删除数据库


/**
  * 删除数据库。
  * dbName:数据库名;
  */
  const deleteDB = (dbName) => {
    // 定义一个 Promise 的实例
    const objectPromise = new Promise((resolve, reject) => {
      // 删掉整个数据库
      myIndexedDB.deleteDatabase(dbName).onsuccess = (event) => {
        resolve(event)
      }
    })
    return objectPromise
  }
复制代码


能建立数据库,那么就应该能删除数据库,这个就是。 这个就非常简单了,不用判断是否打开数据库,直接删除就好。 不过前端数据库应该具备这样的功能:整个库删掉后,可以自动恢复状态才行。


按主键获取对象,或者获取全部


/**
  * 获取对象。
  * storeName:对象仓库名;
  * id:要获取的对象的key值,注意类型要准确,只能取一个。
  * 如果不设置id,会返回store里的全部对象
  */
  const getObject = (storeName, id) => {
    const objectPromise = new Promise((resolve, reject) => {
      const _getObject = () => {
        const tranRequest = _db.transaction(storeName, 'readonly')
        const store = tranRequest.objectStore(storeName) // 获取store
        let dbRequest
        // 判断是获取一个,还是获取全部
        if (typeof id === 'undefined') {
          dbRequest = store.getAll()
        } else {
          dbRequest = store.get(id)
        }
        dbRequest.onsuccess = (event) => { // 成功后的回调
          if (config.debug) {
            console.log('getObject -- onsuccess- event:', id, event)
          }
          resolve(event.target.result) // 返回对象
        }
        tranRequest.onerror = (event) => {
          reject(event)
        }
      }
      // 判断数据库是否打开
      if (typeof _db === 'undefined') {
        dbOpen().then(() => {
          _getObject()
        })
      } else {
        _getObject()
      }
    })
    return objectPromise
  }
复制代码


这里有两个功能


  • 依据ID获取对应的对象


  • 获取对象仓库里的所有对象


不想取两个函数名,于是就依据参数来区分了,传递ID就获取ID的对象,没有传递ID就返回全部。


查询对象仓库


/**
  * 依据 索引+游标,获取对象,可以获取多条。
  * storeName:对象仓库名。
  * page:{
  *   start:开始,
  *   count:数量,
  *   description:'next' 
  *   // next 升序
  *   // prev 降序
  *   // nextunique 升序,只取一
  *   // prevunique 降序,只取一
  * }
  * findInfo = {
  *   indexName: 'groupId',
  *   indexKind: '=', // '>','>=','<','<=','between',
  *   indexValue: 1,
  *   betweenInfo: {
  *     v1:1,
  *     v2:2,
  *     v1isClose:true,
  *     v2isClose:true,
  *   },
  *   where:(object) => {
  *     reutrn true/false
  *   }
  * }
  */
  const findObject = (storeName, findInfo = {}, page = {}) => {
    const _start = page.start || 0
    const _count = page.count || 0
    const _end = _start + _count
    const _description = page.description || 'prev' // 默认倒序
    // 查询条件,按照主键或者索引查询
    let keyRange = null
    if (typeof findInfo.indexName !== "undefined") {
      if (typeof findInfo.indexKind !== "undefined") {
        const id = findInfo.indexValue
        const dicRange = {
          "=":IDBKeyRange.only(id),
          ">":IDBKeyRange.lowerBound(id, true),
          ">=":IDBKeyRange.lowerBound(id),
          "<":IDBKeyRange.upperBound(id, true),
          "<=":IDBKeyRange.upperBound(id)
        }
        switch (findInfo.indexKind) {
          case '=':
          case '>':
          case '>=':
          case '<':
          case '<=':
            keyRange = dicRange[findInfo.indexKind]
            break
          case 'between':
            const betweenInfo = findInfo.betweenInfo
            keyRange = IDBKeyRange.bound(betweenInfo.v1,betweenInfo.v2,betweenInfo.v1isClose,betweenInfo.v2isClose)
            break
        }
      }
    }
    console.log('findObject - keyRange', keyRange)
    const objectPromise = new Promise((resolve, reject) => {
      // 定义个函数,便于调用
      const _findObjectByIndex = () => {
        const dataList = []
        let cursorIndex = 0
        const tranRequest = _db.transaction(storeName, 'readonly')
        const store = tranRequest.objectStore(storeName)
        let cursorRequest 
        // 判断是否索引查询
        if (typeof findInfo.indexName === "undefined") {
          cursorRequest = store.openCursor(keyRange, _description)
        } else {
          cursorRequest = store
            .index(findInfo.indexName)
            .openCursor(keyRange, _description)
        }
        cursorRequest.onsuccess = (event) => {
          const cursor = event.target.result
          if (cursor) {
            if (_end === 0 || (cursorIndex >= _start && cursorIndex < _end)) {
              // 判断钩子函数
              if (typeof findInfo.where === 'function') {
                if (findInfo.where(cursor.value, cursorIndex)) {
                  dataList.push(cursor.value)
                  cursorIndex++
                }
              } else { // 没有设置查询条件
                dataList.push(cursor.value)
                cursorIndex++
              }
            }
            cursor.continue()
          }
          // tranRequest.commit()
        }
        tranRequest.oncomplete = (event) => {
          if (config.debug) {
            console.log('findObjectByIndex - dataList', dataList)
          }
          resolve(dataList)
        }
        tranRequest.onerror = (event) => {
          console.log('findObjectByIndex - onerror', event)
          reject(event)
        }
      }
      // 判断数据库是否打开
      if (typeof _db === 'undefined') {
        dbOpen().then(() => {
          _findObjectByIndex()
        })
      } else {
        _findObjectByIndex()
      }
    })
    return objectPromise
  }
复制代码


打开指定的对象仓库,然后判断是否设置了索引查询,没有的话打开仓库的游标,如果设置了,打开索引的游标。 可以用钩子实现其他属性的查询。 可以分页获取数据,方法类似于mySQL的 limit。


功能测试



封装完毕,要写个测试代码来跑一跑,否则怎么知道到底好不好用呢。 于是写了一个比较简单的测试代码。


建立对象库


dbOpen().then(() =>{
    // 建表初始化之后,获取全部对象
    getAll()
})
复制代码


  • dbOpen


打开数据库,同时判断是否需要建立数据库,如果需要的话,会根据配置信息自动建立数据库


然后我们按F12,打开Application标签,可以找到我们建立的数据库,如图:


image.png


我们可以看一下索引的情况,如图:


image.png


添加对象


addObject('blog',{
          id: new Date().valueOf(),
          groupId: 1,
          title: '这是三个博客',
          addTime: '2020-10-15',
          introduction: '这是博客简介',
          concent: '这是博客的详细内容<br>第二行',
          viewCount: 1,
          agreeCount: 1
        }).then((data) => {
          re.value = data
          getAll()
        })
复制代码


  • 仓库名


第一个参数是对象仓库的名称,目前暂时采用字符串的形式。


  • 对象


第二个参数是要添加的对象,其属性必须有主键和索引,其他随意。


  • 返回值


成功后会返回对象ID


点右键可以刷新数据,如图:


image.png


更新后的数据,如图:


image.png


修改对象


updateObject('blog',blog).then((data) => {
          re.value = data
          getAll()
        })
复制代码


  • 仓库名


第一个参数是对象仓库的名称,目前暂时采用字符串的形式。


  • 对象


第二个参数是要修改的对象,属性可以不全。


  • 返回值


成功后会返回对象ID


删除对象


deleteObject('blog',id).then((data) => {
          re.value = data
          getAll()
        })
复制代码


  • 仓库名


第一个参数是对象仓库的名称,目前暂时采用字符串的形式。


  • 对象


第二个参数是要删除的对象的ID。


  • 返回值


成功后会返回对象ID


清空仓库里的对象


clearStore('blog').then((data) => {
          re.value = data
          getAll()
        })
复制代码


  • 仓库名


第一个参数是对象仓库的名称,目前暂时采用字符串的形式。


  • 返回值


成功后会返回对象ID


删除对象仓库


deleteStore('blog').then((data) => {
          re.value = data
          getAll()
        })
复制代码


  • 仓库名


第一个参数是对象仓库的名称,目前暂时采用字符串的形式。


  • 返回值


成功后会返回对象ID


删除数据库


deleteDB('dbTest').then((data) => {
          re.value = data
          getAll()
        })
复制代码


  • 数据库名称


第一个参数是数据库的名称


查询功能


// 查询条件
      const findInfo = {
        indexName: 'groupId',
        indexKind: '=', // '>','>=','<','<=','between',
        indexValue: 1,
        betweenInfo: {
          v1:1,
          v2:2,
          v1isClose:true,
          v2isClose:true,
        },
        where: (object) => {
          if (findKey.value == '') return true
          let re = false
          if (object.title.indexOf(findKey.value) >= 0) {
            re = true
          }
          if (object.introduction.indexOf(findKey.value) >= 0) {
            re = true
          }
          if (object.concent.indexOf(findKey.value) >= 0) {
            re = true
          }
          return re
        }
      }
      const find = () => {
        findObject('blog', findInfo).then((data) => {
          findRe.value = data
        })
      }
复制代码


  • findInfo


查询信息的对象,把需要查询的信息都放在这里


  • indexName


索引名称,可以不设置。


  • indexKind


索引属性的查询方式,如果设置indexName,则必须设置。


  • indexValue


索引字段的查询值


  • betweenInfo


如果 indexKind = 'between' 的话,需要设置。


  • v1


开始值


  • v2


结束值


  • v1isClose


是否闭合区间


  • v2isClose


是否闭合区间


  • where


钩子函数,可以不设置。 内部打开游标后,会把对象返回来,然后我们就可以在这里进行各种条件判断。


全部代码就不贴了,感兴趣的话可以去GitHub看。 贴一个折叠后的效果图吧:


image.png


就是先把相关的功能和在一起,写一个操作类,然后在setup里面应用这个类就可以了,然后写点代码把各个类关联起来即可。


这样代码好维护多了。


源码



github.com/naturefwvue…


在线演示



naturefwvue.github.io/nf-vue-cnd/…


参考资料



官网:developer.mozilla.org/zh-CN/docs/…


阮一峰的网络日志:www.ruanyifeng.com/blog/2018/0…


谦行: www.cnblogs.com/dolphinX/p/…



相关文章
|
17天前
|
前端开发
理解 ES6 中的 Promise
【10月更文挑战第24天】ES6 中的 Promise 是一种用于处理异步操作的机制,它提供了一种更优雅、更可控的方式来处理异步任务的结果。Promise 可以看作是对异步操作结果的一种承诺,它可以处于三种不同的状态:Pending(等待中)、Fulfilled(已完成,即成功)和 Rejected(已拒绝,即失败)。
|
1月前
|
前端开发 JavaScript 小程序
JavaScript的ES6中Promise的使用以及个人理解
JavaScript的ES6中Promise的使用以及个人理解
18 1
|
1月前
|
前端开发 Java
说说你对es6中promise的理解?
说说你对es6中promise的理解?
13 1
|
1月前
|
前端开发 Java
说说你对es6中promise的理解?
说说你对es6中promise的理解?
|
2月前
|
前端开发 JavaScript
ES6新标准下JS异步编程Promise解读
ES6新标准下JS异步编程Promise解读
36 3
|
1月前
|
存储 前端开发 JavaScript
关于 ES6 中 Promise 的面试题
关于 ES6 中 Promise 的面试题
16 0
|
3月前
|
前端开发
手写实现ES6的Promise.all()和Promise.race()函数
这篇文章介绍了如何手写实现ES6的`Promise.all()`和`Promise.race()`函数,提供了实现这两个Promise聚合函数的详细代码示例,并展示了如何使用它们。
手写实现ES6的Promise.all()和Promise.race()函数
|
6月前
|
前端开发 JavaScript
如何处理 JavaScript 中的异步操作和 Promise?
如何处理 JavaScript 中的异步操作和 Promise?
65 1
|
6月前
|
前端开发 JavaScript
在JavaScript中,什么是promise、怎么使用promise、怎么手写promise
在JavaScript中,什么是promise、怎么使用promise、怎么手写promise
99 4
|
6月前
|
前端开发 JavaScript 开发者
JavaScript 中的异步编程:Promise 和 Async/Await
在现代的 JavaScript 开发中,异步编程是至关重要的。本文将介绍 JavaScript 中的异步编程概念,重点讨论 Promise 和 Async/Await 这两种常见的处理异步操作的方法。通过本文的阐述,读者将能够更好地理解和应用这些技术,提高自己在 JavaScript 开发中处理异步任务的能力。

热门文章

最新文章