js 개발 데이터베이스 공유 예시
프런트엔드는 일부 데이터를 저장해야 하는 경우가 많으며 여기서 저장은 장기 저장을 의미합니다. 이전 아이디어는 데이터를 쿠키에 저장하거나, 키를 쿠키에 저장하고, 다른 데이터는 서버에 저장하는 것이었습니다. 이러한 장면은 용도가 다양하며 매우 성숙하고 사용하기 쉽습니다. 하지만 저는 여전히 데이터베이스나 웹 SQL처럼 로컬에 장기간 저장할 수 있는 데이터를 원합니다.
신세대 브라우저는 기본적으로 로컬 데이터베이스를 지원하므로 필요할 때 직접 사용하세요. 작동하지 않으면 Storage를 사용하여 작업을 수행할 수 있습니다.
데이터베이스 같은 기능이 필요한데 호환되는 저장 방법이 없다면 어떻게 하나요? 이러한 항목을 로컬로 암호화하고 저장해야 합니까? 나는 많은 것을 저장하고 싶다?
현재 ReactNative를 사용할 때 이런 상황이 발생했습니다. 많은 양의 데이터를 로컬에 저장해야 합니다. 누군가는 SQLite를 직접 사용하는 것이 더 좋지 않을까요?
알겠습니다. 전혀 괜찮습니다. 나는 여기서 프론트 엔드 태도로 개발하고 있습니다. 일부 학생에게 SQLite는 필요하지 않지만 대량의 데이터를 저장하는 간단한 방법만 필요한 경우 어떻게 해야 합니까?
사용 시나리오는 다양할 수 있으며, 구현의 맨 아래 레이어를 마음대로 교체할 수 있고, 구현 방법도 마음대로 작성할 수 있습니다. 여기서 나는 세상을 창조하는 프런트엔드의 태도를 바탕으로 비공식적이고 프런트엔드 친화적인 데이터 저장소를 구축하고 있습니다.
기본 스토리지
여기 사용 시나리오는 ReactNative이므로 RN의 AsyncStorage를 사용합니다.
저장할 모든 데이터를 객체와 문자열로 변환합니다. 여기서 핵심 아이디어는 직렬화입니다. 모든 데이터를 문자열로 저장합니다.
import { AsyncStorage } from 'react-native'; exports.setItem = async (key, value) => { let item = JSON.stringify({ v: value }); return await AsyncStorage.setItem(key, item); }
읽을 때 문자열을 원래 저장된 데이터로 변환하려면 변환도 해야 합니다.
exports.getItem = async (key) => { let item = await AsyncStorage.getItem(key); if (!item) { return null; } return JSON.parse(item).v || null; }
특별한 처리가 필요한 것은 목록 획득입니다. RN에는 여러 키를 기반으로 여러 데이터 조각을 반환하는 API가 있습니다. 배열 객체를 반환합니다. 배열 번호 0은 데이터 저장의 키 값이고 시퀀스 번호 1은 데이터 저장의 특정 문자열입니다.
exports.getlist = async (keys) => { let list = await AsyncStorage.multiGet(keys); list = list.map(item => JSON.parse(item[1]).v || null); return list; }
그 밖에도 사용된 몇 가지 방법도 꺼내보겠습니다. 위와 동일한 구성을 유지하면서 여기에 레이어를 하나 더 중첩합니다.
exports.removeItem = async (key) => await AsyncStorage.removeItem(key); exports.removeItems = async (keys) => await AsyncStorage.multiRemove(keys); exports.allKeys = async () => await AsyncStorage.getAllKeys();
기본 최적화
위 내용은 단순한 구현일 뿐 특별한 요구 사항이 없으면 거의 동일합니다. 그러나 더 나아가고 싶은 사람들은 최적화 시작을 고려할 수 있습니다.
예를 들어 json 변환 속도를 최적화하세요. JSON 객체 방식을 사용하여 변환할 때 실제로 숫자형을 결정하는 과정이 있습니다. 데이터 유형을 미리 정의하는 경우. 변환할 때 다시 판단할 필요가 없습니다.
모델 객체를 정의하고 이 테이블에 필요한 필드를 미리 정의할 수 있습니다. Sequelize가 어떻게 정의되어 있는지 확인할 수 있습니다. 관계형 행 데이터베이스의 방식에 따라 이를 수행하는 것은 매우 간단합니다.
//用户对象const users = db.define('t_users', { id: { type: Sequelize.INTEGER, primaryKey: true, }, //用户名 username: { type: Sequelize.STRING }, //密码 pwd: { type: Sequelize.STRING }, //状态 status: { type: Sequelize.INTEGER }, //昵称 nickname: { type: Sequelize.STRING }, //token token: { type: Sequelize.STRING }, create_time: { type: Sequelize.TIME } }, { freezeTableName: true, timestamps: false, });
스토리지 구현
여기서는 관계형 데이터베이스 구현을 참고하겠습니다.
우선 테이블과 데이터베이스를 나누어야 합니다. 이렇게 하면 데이터를 저장할 때 이 정보에 덜 주의를 기울이고 데이터 작업에 집중할 수 있습니다.
constructor(tableName = "table", db = "db") { //检查库,表是否存在 //初始化索引表 this.db = db; this.tableName = tableName; this.tableKey = db + "_" + tableName; this.init(); }
현재 객체 내부에 별도로 저장하세요. 객체 생성 시 다양한 라이브러리와 테이블을 기반으로 다양한 작업 방법을 생성할 수 있습니다. 여기서는 클래스가 사용되며 각 테이블은 별도의 개체에 해당합니다.
RN에서 제공하는 저장 방식을 사용하고 있기 때문에 여기서 추가와 업데이트는 사실 동일한 방식입니다. 추가 시 현재 타임스탬프를 기준으로 고유 ID가 생성되며, 이 ID는 데이터베이스에 저장하기 위한 키로 사용됩니다. 따라서 사용시 ID를 별도로 저장할 필요는 없습니다. 다만, 필요한 ID와 다르다고 생각되면 직접 ID를 정의하여 키 값을 저장할 수도 있습니다.
//添加和更新 async add(data = {}) { if (data.constructor !== Object) return; if (!data._id)data._id = uuid(); await setItem(this.tableKey + "_" + data._id, data); return data; }
획득 시 ID별로 획득 방법을 별도로 제공하고 있습니다. 여기서 고려되는 점은 ID로 얻는 것이 매우 간단하고 편리하다는 것입니다. 일부 데이터는 빠르게 읽을 수 있으며 한 줄씩 쿼리할 필요가 없습니다.
/** * 通过id查询 * @param {*} id */async getById(id) { if (!id) return {}; return await getItem(this.tableKey + "_" + id); }
ID 기반 쿼리에 비해 퍼지 쿼리는 실제로 매우 느립니다. 실제로 필요하지 않은 경우에는 이 퍼지 쿼리를 사용하지 않는 것이 좋습니다. 여기에는 반환된 개체를 기반으로 이 데이터 행이 필요한지 여부를 결정할 수 있는 사용자 지정 쿼리 메서드가 제공됩니다. 반환되는 수를 제한하기 위해 top 매개변수를 추가할 수도 있습니다. 이 매개변수를 사용하면 데이터가 많을 때 성능이 향상될 수도 있습니다.
/** * 通过过滤方法查询 * @param {*} fn */async get(fn, top = 0) { let keys = await allKeys(); if (keys.length == 0) return []; if (top > 0 && keys.length > top) keys.length = top; const listkey = keys.filter(item => item.indexOf(this.tableKey + "_") === 0); if (listkey.length == 0) return []; let list = await getlist(listkey); list = list.filter(item => fn(item)); return list; }
드디어 삭제, 삭제 메소드를 추가하면 간단한 삭제 라이브러리가 완성됩니다.
/** * 删除 * @param {*} id */async delete(id) { if (!id) return {}; await removeItem(this.tableKey + "_" + id); }/** * 清空表 */async clear() { let keys = await allKeys(); const listkey = keys.filter(item => item.indexOf(this.tableKey + "_") === 0); if (listkey.length == 0) return; removeItems(listkey); }
사용시에는 객체를 생성한 후 필요한 곳에 호출하기만 하면 됩니다. 사용이 간단하고 편리하며, 최적화 후에는 클라이언트측 Redis로도 사용할 수 있습니다.
//初始化数据库let db=new JSDB();//添加一个自定义数据db.add({name:"test",key:"abc"});//根据id获取数据db.getById("1223467890");//根据条件查询数据db.get(d=>d.name==="test");//删除对应的数据db.delete("1223467890");//情况所有数据db.clear()
생성 최적화
최초로 최적화해야 할 것은 객체 생성입니다. 각 객체 생성에는 실제로 많은 돈이 소비됩니다. 이 소비를 줄일 수 있다면 좋지 않을까요?
여기에서는 데이터베이스 풀의 개념을 배우고 개체 풀 방법을 구현합니다. 객체가 생성된 후에는 직접적인 반환이 없으며 풀 작업을 거쳐야 합니다.
객체를 풀에 넣고 페이지가 파괴되면 빈 객체로 재설정합니다. 다음에 요청할 때 새 항목을 생성할 필요가 없습니다. 테이블이나 라이브러리의 이름을 직접 지정하여 사용할 수 있습니다. 기억은 변함이 없어 좀 웃게 만드네요.
쿼리 최적화
쿼리할 때마다 Stroage를 읽는 것은 여전히 매우 번거로운 작업입니다. 특히 이 작업은 비동기 작업이므로 네이티브 측에 메시지를 보내야 합니다.
마지막으로 읽은 데이터를 변수에 저장할 수 있습니다. 다음에 이 데이터 줄을 사용해야 하는 경우 다시 읽을 필요가 없습니다. 이는 읽기 속도를 쉽게 제공할 수 있습니다.
이 방법은 계속해서 최적화될 수 있습니다. 변수에 저장되는 데이터의 양을 제한하여 앱 한도를 초과하지 않도록 하세요. 또한 저장 기한을 논리적으로 판단하여 자주 사용하는 데이터를 넣어두고, 자주 사용하지 않는 데이터는 삭제할 기회를 찾을 수도 있습니다.
이 방법을 사용하면 변수의 데이터 효율성을 최적화하고 변수가 차지하는 메모리 크기를 줄일 수도 있습니다. 하지만 구현 방법에서는 타이머를 사용하지 않도록 하세요. 트리거 유형을 사용하는 것도 고려해 보세요. 조건이 충족되면 삭제 작업이 트리거됩니다.
글쓰기 최적화
위에서 언급했듯이 읽기 속도를 높이려면 읽을 때 변수를 넣어야 합니다. 그런데 쓰기 속도도 향상될 수 있을까?
저장할 데이터를 임시 변수에 넣어두었습니다. 설정한 시간이나 데이터 길이를 확인하고 설정한 수량을 확인하면 저장 작업이 실행됩니다.
여기서 주의할 점은 데이터 저장에 사용되는 변수와 저장 시 사용되는 변수는 데이터 손실을 방지하기 위해 서로 바꿔서 사용해야 한다는 점입니다.
예: 저장할 때 변수 1을 사용합니다. 데이터베이스에 쓰기 전에 저장할 개체를 변수 2로 변경한 다음 변수 1의 데이터를 읽어 데이터베이스에 저장합니다. 이는 이중 버퍼링 쓰기입니다.
물론, 앱의 종료 이벤트를 결정해야 합니다. 앱이 종료되면 해당 내용을 변수에 한 번 저장해 두시기 바랍니다. 그렇지 않으면 모든 노력이 손실됩니다.
자, 간단한 데이터베이스가 완성되었습니다. 사용하시려면 먼저 npm에서 이 라이브러리를 검색하시면 됩니다. 구현의 첫 번째 부분을 npm에 넣었으며 후속 최적화는 완전히 오픈 소스화될 것입니다. react-native-jsdb
import { AsyncStorage } from 'react-native'; exports.setItem = async (key, value) => { let item = JSON.stringify({ v: value }); return await AsyncStorage.setItem(key, item); }
exports.getItem = async (key) => { let item = await AsyncStorage.getItem(key); if (!item) { return null; } return JSON.parse(item).v || null; }
exports.getlist = async (keys) => { let list = await AsyncStorage.multiGet(keys); list = list.map(item => JSON.parse(item[1]).v || null); return list; }
exports.removeItem = async (key) => await AsyncStorage.removeItem(key); exports.removeItems = async (keys) => await AsyncStorage.multiRemove(keys); exports.allKeys = async () => await AsyncStorage.getAllKeys();
//用户对象const users = db.define('t_users', { id: { type: Sequelize.INTEGER, primaryKey: true, }, //用户名 username: { type: Sequelize.STRING }, //密码 pwd: { type: Sequelize.STRING }, //状态 status: { type: Sequelize.INTEGER }, //昵称 nickname: { type: Sequelize.STRING }, //token token: { type: Sequelize.STRING }, create_time: { type: Sequelize.TIME } }, { freezeTableName: true, timestamps: false, });
constructor(tableName = "table", db = "db") { //检查库,表是否存在 //初始化索引表 this.db = db; this.tableName = tableName; this.tableKey = db + "_" + tableName; this.init(); }
将它们分开存储在当前对象内部,在创建对象的时候就可以根据不同的库、表创建不同的操作方法。这里使用的是class,每个表都对应一个单独的对象。
由于我们使用的是RN提供的存储方法,所以这里的添加和更新其实是一个方法。在添加的时候会根据当前时间戳创建一个唯一id,使用这个id作为key存储在数据库中。所以在使用的时候不需要再单独存入id,不过如果你觉得这个id跟你需要的有差别也可以自己定义一个id来作为key值存储。
//添加和更新 async add(data = {}) { if (data.constructor !== Object) return; if (!data._id)data._id = uuid(); await setItem(this.tableKey + "_" + data._id, data); return data; }
在获取的时候单独提供了一个根据id获取的方式。这里考虑的是通过id获取非常的简单方便,对于某些数据完全可以快速读取,没必要一行一行的去查询。
/** * 通过id查询 * @param {*} id */async getById(id) { if (!id) return {}; return await getItem(this.tableKey + "_" + id); }
相对于根据id查询来说,模糊查询确实很慢,如果不是真实需要,还是不要使用这种模糊查询的好。这里提供了一个自定义查询的方法,可以根据返回的对象判断是否需要这行数据。同时也可以添加top参数来限制返回的数量。使用这个参数也可以在数据很多的时候提高性能。
/** * 通过过滤方法查询 * @param {*} fn */async get(fn, top = 0) { let keys = await allKeys(); if (keys.length == 0) return []; if (top > 0 && keys.length > top) keys.length = top; const listkey = keys.filter(item => item.indexOf(this.tableKey + "_") === 0); if (listkey.length == 0) return []; let list = await getlist(listkey); list = list.filter(item => fn(item)); return list; }
最后把删除和清空的方法加上,这样一个简单的删除库就完成了。
/** * 删除 * @param {*} id */async delete(id) { if (!id) return {}; await removeItem(this.tableKey + "_" + id); }/** * 清空表 */async clear() { let keys = await allKeys(); const listkey = keys.filter(item => item.indexOf(this.tableKey + "_") === 0); if (listkey.length == 0) return; removeItems(listkey); }
使用的时候只需要创建对象,然后在需要的地方调用即可。使用起来简单又方便,再加上优化之后的情况甚至可以当成客户端的redis来使用。
//初始化数据库let db=new JSDB();//添加一个自定义数据db.add({name:"test",key:"abc"});//根据id获取数据db.getById("1223467890");//根据条件查询数据db.get(d=>d.name==="test");//删除对应的数据db.delete("1223467890");//情况所有数据db.clear()
优化创建
首先要优化的就是对象的创建。每个对象创建其实都是一个很大的消耗,如果能把这个消耗降低岂不是美滋滋!
这里我们借鉴数据库池的概念,实现一个对象池的方法。在对象创建之后并没有直接返回,要在经过池的操作。
将对象放入池内,并在页面销毁的时候重置为一个空对象。下次请求创建的时候就不必再创建新的了。直接赋值表、库的名称就可以使用了。内存毫无变化,并且有点想笑。
优化查询
每次查询都需要去读Stroage还是很麻烦的,尤其这个操作是异步操作,是需要发消息到native端的。
我们可以将上次读取的数据先存在一个变量中,如果下次还需要使用这行数据,就完全不需要再去读取了。这样就可以很简单的提供读取速度。
这个方式还可以继续优化。将变量中保存的数据限制数量,防止数量太多超过了APP的限制。还可以将这个保存的时限做一个逻辑判断,常使用的数据放在里面,不常用的就找机会删除。
使用这种方式也可以优化变量中数据的有效性,减少变量占用内存的大小。不过实现的方式尽量不要使用定时器的形式,可以考虑使用触发式的。在条件满足的时候再触发删除动作。
优化写入
上面提到读取的时候需要放入变量来提高读取速度。我们顺便想到写入的速度是不是也可以提高啊?
我们将要存的数据放在临时的变量里,如果查过我们设置的时间或者数据长度查过我们设置的数量就触发一次保存操作。
这里要注意,保存数据的变量和存入时候使用的变量要交替使用,防止出现丢数据的情况。
比如:存的时候使用变量1,在写到数据库之前,将要存的对象改成变量2,然后读取变量1的数据并存入数据库中。这就是双缓存写入。
当然还是要判断一次APP的退出事件的,如果APP退出了,请一定要把变量中的内容保存一次,不然你的心血就全丢了。
好了,一个简单的数据库就完成了。想要使用的可以先在npm上搜索react-native-jsdb
这个库。我已经将第一部分实现放在了npm上,后续的优化也会满满的开源出来的。
위 내용은 js 개발 데이터베이스 공유 예시의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

핫 AI 도구

Undresser.AI Undress
사실적인 누드 사진을 만들기 위한 AI 기반 앱

AI Clothes Remover
사진에서 옷을 제거하는 온라인 AI 도구입니다.

Undress AI Tool
무료로 이미지를 벗다

Clothoff.io
AI 옷 제거제

AI Hentai Generator
AI Hentai를 무료로 생성하십시오.

인기 기사

뜨거운 도구

메모장++7.3.1
사용하기 쉬운 무료 코드 편집기

SublimeText3 중국어 버전
중국어 버전, 사용하기 매우 쉽습니다.

스튜디오 13.0.1 보내기
강력한 PHP 통합 개발 환경

드림위버 CS6
시각적 웹 개발 도구

SublimeText3 Mac 버전
신 수준의 코드 편집 소프트웨어(SublimeText3)

뜨거운 주제











Go 언어는 효율적이고 간결하며 배우기 쉬운 프로그래밍 언어입니다. 동시 프로그래밍과 네트워크 프로그래밍의 장점 때문에 개발자들이 선호합니다. 실제 개발에서 데이터베이스 작업은 필수적인 부분입니다. 이 기사에서는 Go 언어를 사용하여 데이터베이스 추가, 삭제, 수정 및 쿼리 작업을 구현하는 방법을 소개합니다. Go 언어에서는 일반적으로 사용되는 SQL 패키지, Gorm 등과 같은 타사 라이브러리를 사용하여 데이터베이스를 운영합니다. 여기서는 sql 패키지를 예로 들어 데이터베이스의 추가, 삭제, 수정 및 쿼리 작업을 구현하는 방법을 소개합니다. MySQL 데이터베이스를 사용하고 있다고 가정합니다.

Hibernate 다형성 매핑은 상속된 클래스를 데이터베이스에 매핑할 수 있으며 다음 매핑 유형을 제공합니다. Join-subclass: 상위 클래스의 모든 열을 포함하여 하위 클래스에 대한 별도의 테이블을 생성합니다. 클래스별 테이블: 하위 클래스별 열만 포함하는 하위 클래스에 대한 별도의 테이블을 만듭니다. Union-subclass: Joined-subclass와 유사하지만 상위 클래스 테이블이 모든 하위 클래스 열을 통합합니다.

Apple의 최신 iOS18, iPadOS18 및 macOS Sequoia 시스템 릴리스에는 사진 애플리케이션에 중요한 기능이 추가되었습니다. 이 기능은 사용자가 다양한 이유로 손실되거나 손상된 사진과 비디오를 쉽게 복구할 수 있도록 설계되었습니다. 새로운 기능에는 사진 앱의 도구 섹션에 '복구됨'이라는 앨범이 도입되었습니다. 이 앨범은 사용자가 기기에 사진 라이브러리에 포함되지 않은 사진이나 비디오를 가지고 있을 때 자동으로 나타납니다. "복구된" 앨범의 출현은 데이터베이스 손상으로 인해 손실된 사진과 비디오, 사진 라이브러리에 올바르게 저장되지 않은 카메라 응용 프로그램 또는 사진 라이브러리를 관리하는 타사 응용 프로그램에 대한 솔루션을 제공합니다. 사용자는 몇 가지 간단한 단계만 거치면 됩니다.

MySQLi를 사용하여 PHP에서 데이터베이스 연결을 설정하는 방법: MySQLi 확장 포함(require_once) 연결 함수 생성(functionconnect_to_db) 연결 함수 호출($conn=connect_to_db()) 쿼리 실행($result=$conn->query()) 닫기 연결( $conn->close())

PHP에서 데이터베이스 연결 오류를 처리하려면 다음 단계를 사용할 수 있습니다. mysqli_connect_errno()를 사용하여 오류 코드를 얻습니다. 오류 메시지를 얻으려면 mysqli_connect_error()를 사용하십시오. 이러한 오류 메시지를 캡처하고 기록하면 데이터베이스 연결 문제를 쉽게 식별하고 해결할 수 있어 애플리케이션이 원활하게 실행될 수 있습니다.

HTML은 데이터베이스를 직접 읽을 수 없지만 JavaScript 및 AJAX를 통해 읽을 수 있습니다. 단계에는 데이터베이스 연결 설정, 쿼리 보내기, 응답 처리 및 페이지 업데이트가 포함됩니다. 이 기사에서는 JavaScript, AJAX 및 PHP를 사용하여 MySQL 데이터베이스에서 데이터를 읽는 실제 예제를 제공하고 쿼리 결과를 HTML 페이지에 동적으로 표시하는 방법을 보여줍니다. 이 예제에서는 XMLHttpRequest를 사용하여 데이터베이스 연결을 설정하고 쿼리를 보내고 응답을 처리함으로써 페이지 요소에 데이터를 채우고 데이터베이스를 읽는 HTML 기능을 실현합니다.

Go 표준 라이브러리 데이터베이스/sql 패키지를 통해 MySQL, PostgreSQL 또는 SQLite와 같은 원격 데이터베이스에 연결할 수 있습니다. 데이터베이스 연결 정보가 포함된 연결 문자열을 생성합니다. sql.Open() 함수를 사용하여 데이터베이스 연결을 엽니다. SQL 쿼리 및 삽입 작업과 같은 데이터베이스 작업을 수행합니다. 리소스를 해제하기 위해 defer를 사용하여 데이터베이스 연결을 닫습니다.

Golang의 데이터베이스 콜백 기능을 사용하면 다음을 달성할 수 있습니다. 지정된 데이터베이스 작업이 완료된 후 사용자 정의 코드를 실행합니다. 추가 코드를 작성하지 않고도 별도의 함수를 통해 사용자 정의 동작을 추가할 수 있습니다. 삽입, 업데이트, 삭제, 쿼리 작업에 콜백 함수를 사용할 수 있습니다. 콜백 함수를 사용하려면 sql.Exec, sql.QueryRow, sql.Query 함수를 사용해야 합니다.
