如何让JavaScript的appendElement函数等待createForm及updateValues执行完成(无需setTimeout)?
解决方案:用Promise等待用户交互完成
我明白你的问题了——你当前的async/await根本没起到等待作用,因为createForm里的await updateValues(number)是函数执行时立刻同步调用的,但实际上updateValues是用户点击"Add"按钮才会触发的操作,这时候createForm早就跑完了,addPlace里的appendElement自然不会等用户输入完成。
咱们用Promise来包裹用户的交互逻辑,让createForm返回一个Promise,只有当用户完成点击操作、updateValues执行完毕后,这个Promise才会resolve,这样addPlace里的await就能真正等待用户操作完成。
修改步骤&核心代码
1. 改造createForm,让它返回Promise
把用户的交互操作包裹在Promise里,保存resolve函数,等用户点击按钮时再触发它:
// 改造createForm,返回Promise function createForm(number){ return new Promise((resolve) => { console.log(`locationName_${number}`); let items = `key, phone, book,...`; let newForm = ` <div id="container" class="d-flex align-items-stretch"> <div class="reveal-modal d-flex flex-column bd-highlight mb-3" id="exampleModal"> <div class="mb-3 d-flex flex-column "> <label for="locationName" class="form-label">Location</label> <input type="name" class="form-control" id="updateLocationName_${number}" placeholder="Location Name"> <label for="Lost items" class="form-label">Lost items<br>Please separate items with comma (,)</label> <input type="name" class="form-control" id="updatedLocationItems_${number}" placeholder="${items}"> </div> <div> <button class="btn btn-primary" onclick="deleteListCard('container')">Cancel</button> <!-- 修改按钮点击事件,传入resolve函数 --> <button class="btn btn-primary" onclick="updateValues(${number}, resolve)">Add</button> </div> </div> </div> `; const parentDom = document.querySelector('body'); parentDom.innerHTML += newForm; }); }
2. 调整updateValues,完成操作后resolve Promise
让updateValues接收resolve参数,在完成localStorage设置和弹窗关闭后,触发resolve告知Promise完成:
// 接收resolve参数,完成后触发resolve async function updateValues(number, resolve){ console.log(`${number} is updated!`); let updatedName = document.getElementById(`updateLocationName_${number}`).value; let updatedItems = document.getElementById(`updatedLocationItems_${number}`).value; console.log(updatedName); console.log(updatedItems); const itemArr = updatedItems.split(','); // 存入localStorage localStorage.setItem(`locationName_${number}`, updatedName); localStorage.setItem(`locationItems_${number}`, JSON.stringify(itemArr)); deleteListCard('container'); // 关闭弹窗 // 触发resolve,告诉createForm的Promise已完成 resolve(); }
3. 保留原addPlace逻辑即可
现在addPlace里的await createForm(idNum)会真正等待用户操作完成,再执行appendElement:
async function addPlace (){ await createForm(idNum); appendElement("listParent", idNum); idNum += 1; };
完整修改后代码
async function addPlace (){ await createForm(idNum); appendElement("listParent", idNum); idNum += 1; }; // 改造createForm,返回Promise function createForm(number){ return new Promise((resolve) => { console.log(`locationName_${number}`); let items = `key, phone, book,...`; let newForm = ` <div id="container" class="d-flex align-items-stretch"> <div class="reveal-modal d-flex flex-column bd-highlight mb-3" id="exampleModal"> <div class="mb-3 d-flex flex-column "> <label for="locationName" class="form-label">Location</label> <input type="name" class="form-control" id="updateLocationName_${number}" placeholder="Location Name"> <label for="Lost items" class="form-label">Lost items<br>Please separate items with comma (,)</label> <input type="name" class="form-control" id="updatedLocationItems_${number}" placeholder="${items}"> </div> <div> <button class="btn btn-primary" onclick="deleteListCard('container')">Cancel</button> <!-- 修改按钮点击事件,传入resolve函数 --> <button class="btn btn-primary" onclick="updateValues(${number}, resolve)">Add</button> </div> </div> </div> `; const parentDom = document.querySelector('body'); parentDom.innerHTML += newForm; }); } // 接收resolve参数,完成后触发resolve async function updateValues(number, resolve){ console.log(`${number} is updated!`); let updatedName = document.getElementById(`updateLocationName_${number}`).value; let updatedItems = document.getElementById(`updatedLocationItems_${number}`).value; console.log(updatedName); console.log(updatedItems); const itemArr = updatedItems.split(','); // set Array localStorage.setItem(`locationName_${number}`, updatedName); localStorage.setItem(`locationItems_${number}`, JSON.stringify(itemArr)); deleteListCard('container'); //exit popup // 触发resolve,告诉createForm的Promise已经完成 resolve(); } //Append List function appendElement(parentID, number){ const parentDom = document.getElementById(parentID); if(document.getElementById("stevens_barbar")){ deleteListCard("stevens_barbar"); } let location = localStorage.getItem(`locationName_${number}`); let storedItems = JSON.parse(localStorage.getItem(`locationItems_${number}`)); parentDom.innerHTML += ` <div id="location_${number}"> <h1>${location}</h1> ${generateCheckbox(storedItems)} <div> <button class="btn btn-primary" onclick="updateLocalstorage('${number}')">Edit</button> <button class="btn btn-warning delete_button" onclick="deleteListCard('location_${number}')">Delete</button> </div> </div> `; }
这样修改后,你不需要刷新页面,appendElement创建的卡片会直接读取最新的localStorage值,完美解决你的问题。
内容的提问来源于stack exchange,提问作者Kawa
相关产品推荐
相关产品推荐

