SharePoint 2013中Promise处理REST更新后HTML重载问题
问题描述
我自认为理解Promise,但实际运用仍有困惑。我基于SharePoint 2013开发了一款应用,通过sprLib发起REST请求填充数据对象,支持完整的CRUD操作(新增、删除、更新条目),并能将变更同步回列表,这部分功能目前运行正常。现在我希望在执行更新操作后,先清空div标签,再调用初始加载函数重新渲染最新的列表数据,但目前要么出现Promise语法错误,要么因竞态条件导致初始加载函数在更新完成前就执行,最终渲染的仍是旧列表。我制作了一个简化版本模拟该场景(未包含REST更新逻辑):
简化场景代码
JavaScript代码
const fullList = [ // 真实环境中通过REST接口填充 { id: "12", title: "A", code: "110" }, { id: "23", title: "B", code: "120" }, { id: "13", title: "C", code: "130" }, { id: "43", title: "D", code: "140" }, { id: "52", title: "E", code: "150" }, ] $(document).ready(function () { initialLoad(fullList); $('#updateList').click(function() { let item = $('#txtValue').val(); addToList(item).then(function(result){ console.log('add complete'); initialLoad(fullList); console.log('reloaded'); }) .catch(function(){ console.log('fail'); }) }); }) function initialLoad(list) { // 真实环境中是用sprLib执行getItem操作 $('#itemList').empty(); let listHTML = '' for (i = 0; i < list.length; i++) { listHTML += '<p>'+list[i].title+' ' +list[i].code+'</p>' } $('#itemList').append(listHTML); } function addToList(entry) { return new Promise(function(resolve, reject) { console.log('I go first'); fullList.push({ 'id': "", 'title': entry, 'code': ""}); // 真实环境中是用sprLib执行CRUD操作 setTimeout(() => resolve("done"), 5000); }); }
HTML代码
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Promise</title> <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.0-beta1/dist/js/bootstrap.bundle.min.js" integrity="sha384-pprn3073KE6tl6bjs2QrFaJGz5/SUsLqktiwsUTF55Jfv3qYSDhgCecCxMW52nD2" crossorigin="anonymous"></script> <script src="https://code.jquery.com/jquery-3.6.0.min.js" type="text/javascript"></script> <script src="https://cdn.datatables.net/1.12.1/js/jquery.dataTables.min.js" type="text/javascript"></script> <script src="/scripts/promise.js"></script> <link href="https://cdn.datatables.net/1.12.1/css/jquery.dataTables.min.css" rel="stylesheet"> <link href="https://cdn.datatables.net/select/1.4.0/css/select.dataTables.min.css" rel="stylesheet"> <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.0-beta1/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-0evHe/X+R7YkIZDRvuzKMRqM+OrBnVFBL6DOitfPri4tjfHxaWutUpFmBp4vmVor" crossorigin="anonymous"> </head> <body><br><br> <div class="container text-center row"> <div class="card col-2 bg-primary text-light" id="itemList"> </div> <div class="card col-2 bg-secondary"><input type="text" class="form" id="txtValue"> <button type="button" class="btn btn-success" id="updateList">Submit</button></div> </div> </body> </html>
解决方案
你的简化代码逻辑本身是正确的,但实际SharePoint场景中出现问题,核心原因通常是没有正确等待sprLib的异步操作完成,或者依赖内存中的数据而非重新拉取最新数据。以下是针对性解决办法:
1. 改用async/await简化Promise逻辑
链式then/catch容易出现语法错误,改用async/await能让异步代码的执行顺序更直观,降低出错概率。
2. 避免依赖内存数据,重新拉取最新数据
实际场景中不要依赖全局的fullList,每次渲染前通过sprLib重新获取列表数据,彻底避免内存数据与SharePoint列表不一致的问题。
修正后的实际场景代码
$(document).ready(function () { // 初始加载最新数据 loadListData(); $('#updateList').click(async function() { let item = $('#txtValue').val(); try { // 等待sprLib新增操作完全完成 await addToList(item); console.log('新增完成'); // 重新加载并渲染最新数据 await loadListData(); console.log('重新加载完成'); } catch (error) { console.error('操作失败:', error); } }); }) // 封装加载数据函数:清空div → 拉取最新数据 → 渲染 async function loadListData() { $('#itemList').empty(); // 通过sprLib获取SharePoint列表最新数据 const latestItems = await sprLib.list('你的列表名称').items().get(); let listHTML = ''; for (const item of latestItems) { listHTML += `<p>${item.Title} ${item.Code}</p>`; } $('#itemList').append(listHTML); } // 封装新增操作:返回sprLib的Promise对象 async function addToList(entry) { // sprLib的create方法默认返回Promise,直接返回即可 return await sprLib.list('你的列表名称').create({ Title: entry, Code: '' }); }
关键说明
- 确保异步操作顺序:通过
await保证新增操作完全完成后,再执行数据拉取和渲染,彻底解决竞态条件问题。 - 数据来源可靠:每次渲染都从SharePoint拉取最新数据,避免内存数据过期导致的旧数据渲染。
- 代码可读性提升:async/await替代链式then/catch,逻辑更清晰,减少语法错误概率。
内容的提问来源于stack exchange,提问作者Eric Smith
相关产品推荐
相关产品推荐

