目次
分析
データベースを操作した後に、以下のようなレスポンスが返されていることを確認した上で、データの再取得を実施。
しかし、登録・削除されたはずのデータが反映されていなかった。
-> POST http://hogehoge:9200/memo/_doc
{
"memo": {
"message": "テスト",
"created": "2022-06-27T07:54:29.564Z"
}
}
<- 201
{
"_index": "memo",
"_type": "_doc",
"_id": "SGsnpIEBPjJae6aOoV1l",
"_version": 1,
"result": "created",
"_shards": {
"total": 2,
"successful": 1,
"failed": 0
},
"_seq_no": 162,
"_primary_term": 1
}
TRACE: 2022-06-27T12:46:27Z
-> DELETE http://hogehoge:9200/memo/_doc/SGsnpIEBPjJae6aOoV1l
<- 200
{
"_index": "memo",
"_type": "_doc",
"_id": "SGsnpIEBPjJae6aOoV1l",
"_version": 2,
"result": "deleted",
"_shards": {
"total": 2,
"successful": 1,
"failed": 0
},
"_seq_no": 183,
"_primary_term": 1
}
【問題の考察】
- サーバ側のデータベースの処理が終わっていない状態なので、更新前のデータを受け取っている
クライアント側のキャッシュが残っていて、悪さをしている(多分違う)
解決策
データベースが更新されるまで、どうにかして待つ!
おまけ
今回、問題が発生したメモ帳では、Submitの前にデータベース操作を行い、その後にSubmitによってページ全体のリロードが実行され、ページを再読み込みするタイミングで、データベースの情報を引き出していた。しかし、これではリロードが早すぎたようで、上記の通りデータベースが更新される前にデータの取得が行われてしまい、古い情報を取得していた。
①DB操作のステータスを参照できるように返り値に設定する
export async function save(type, data) {
if(type[0] == "mode"){
const update = await client.update({
index: index_name,
id: type[1],
body: {
doc:{
mode:data.mode,
find:data.find
}
}
})
/**以下を追加 */
return update;
}else if(type[0] == "memo"){
const add = await client.index({
index: index_name,
body: {
memo:{
message:data.message,
created:data.created
}
}
})
/**以下を追加 */
return add;
}
}
/********** 中略 **********/
export async function del(data_id) {
const del = await client.delete({
index: index_name,
id: data_id
})
/**以下を追加 */
return del;
}
②DB操作が反映されたかをチェックする関数を作成
/**以下を追加 */
async function search_status(data_id) {
const search = await client.search({
index: index_name,
body: {
query: {
ids: {
values: data_id
}
}
}
})
console.log(search);
return search;
}
/**以下を追加 */
export async function check(data_id, hits){
const sleep = msec => new Promise(resolve => setTimeout(resolve, msec));
for (let i = 0; i < 6; i++) {
try {
let search = await search_status(data_id);
if(search.hits.hits.length == hits){
return true;
}
} catch (error) {
console.log(error);
}
await sleep(500);
}
return false;
}
③サーバ側でDB操作が完了したのを確認してからリロードするように、呼び出し元のコードを改良
import React, {useState, useEffect} from 'react'
import * as ELController from'./ELController'
export default function AddForm(props) {
const [message, setMessage] = useState('')
const doChange = (e)=> {
setMessage(e.target.value)
}
const doAction = (e)=> {
/**以下を追加 */
e.preventDefault();
const data = {
message: message,
created: new Date()
}
const f = async (d) => {
const res = await ELController.save(["memo"], d)
setMessage(' ')
/**以下を追加 */
let check = await ELController.check(res._id, 1);
if(check){
window.location.reload();
}else{
alert("メモの登録に時間がかかっているか、登録に失敗しました。")
}
}
f(data)
}
return (
<form id="add" onSubmit={doAction} action="">
<div className="form-group row">
<input type="text" className="form-control-sm col" onChange={doChange} value={message} required />
<input type="submit" value="Add" className="btn btn-primary btn-sm col-2" />
</div>
</form>
)
}
import React, {useState, useEffect} from 'react'
import * as ELController from'./ELController'
export default function DelForm(props) {
const [memo, setMemo] = useState([])
useEffect(
() => {
const f = async () => {
const res = await ELController.load("memo", "")
setMemo(res)
}
f();
},
[]
);
const [id, setId] = useState("")
const doChange = (e)=> {
setId(e.target.value)
}
const doAction = (e)=> {
/**以下を追加 */
e.preventDefault();
const f = async (d) => {
// No1だけ消えない>>IDが入ってない???>>先頭にダミーを置いた
const res = await ELController.del(d)
setId("")
/**以下を追加 */
let check = await ELController.check(res._id, 0);
if(check){
window.location.reload();
}else{
alert("メモの削除に時間がかかっているか、削除に失敗しました。")
}
}
f(id);
}
let items = memo.map((value,key)=>(
<option key={key} value={value.id}>
{value.message.substring(0,10)}
</option>
))
return (
<form onSubmit={doAction}>
<div className="form-group row">
<select onChange={doChange} className="form-control-sm col" defaultValue="-1">
<option disabled selected value>削除するメモを選択</option>
{items}
</select>
<input type="submit" value="Del" className="btn btn-primary btn-sm col-2" />
</div>
</form>
)
}
e.preventDefault();
をやって、Submit
する(Post
とかGet
が走る)のをいったん止める。
今回は、別に値をSubmit
する必要はないので、DBの操作が反映されたのを確認した段階で、window.location.reload();
を実行した。