如何解决使用第 n 个 REST 调用为网络工作者的 onmessage 事件创建承诺
我正在使用网络工作者以递归方式获取网站信息,包括其子网站(第 n 个编号)。当所有调用完成后,我想触发一个函数来格式化它接收到的数据(allSites 数组)。所以我认为将 Promise.all 与一个包含我所有已解决承诺的对象一起使用是一个好主意。
问题在于它不会等待所有已解决的承诺,因为它正在等待从工作人员发布的消息。我无法定义长度,因为它可以是任意数量的网站 + 子网站。
奖励:我有一个已解决承诺的对象。我可以这样调用某个确定吗?
keyName[index]()
它说它不是一个函数,但我不应该这样调用它吗?非常感谢任何帮助。
function getTreeData(cb) {
let allSites = [];
let baseUrl = "https://www.somewebsite.com/"
let resolver = {};
let rejecter = {};
let workerUrl =
"https://www.somewebsite.com/siteassets/worker.js";
let myWorker = new Worker(workerUrl);
function firstIteration() {
return new Promise((resolve,reject) => {
resolver[baseUrl] = resolve;
rejecter[baseUrl] = reject;
myWorker.postMessage({
requestDigest: document.getElementById("__REQUESTDIGEST").value,qs1: "/_api/web/webinfos?$select=ServerRelativeUrl,Title",qs2:
"/_api/Web/RoleAssignments?$expand=Member/Users,RoleDefinitionBindings",url: baseUrl,});
});
}
firstIteration();
//spawn a worker
myWorker.onmessage = function (e) {
allSites = allSites.concat([
{ pathname: e.data.url,groups: e.data.permissions },]);
e.data.sites.forEach(function (props) {
return new Promise((resolve,reject) => {
myWorker.postMessage({
requestDigest: document.getElementById("__REQUESTDIGEST").value,qs2:
"/_api/Web/RoleAssignments?$expand=Member/Users,url: "www.somewebsite.com" + props.url,});
resolver[props.url] = resolve;
rejecter[props.url] = reject;
});
});
resolver[e.data.url](); //it says that it is not a function
};
myWorker.onerror = function (e) {
rejecter[e.data.url]();
};
//After my first inital promises resovles resolve the rest (checks object of resolves)
resolver[baseUrl]().then(() => {
Promise.all(Object.values(resolver)).then(() => {
reduceData(cb,allSites);
});
});
}
虽然它工作正常,但这里是网络工作者的代码。 (worker.js)
function formatSites(props) {
return {
url: "www.someSite.com",};
}
function formatSitesInfo(props) {
//get all info of the site or subsite
var accessArr = props.RoleDefinitionBindings.results
.reduce(function (r,a) {
return r.concat([a.Name]);
},[])
.sort()
.join(",");
return {
access: accessArr,isGroup: props.Member.hasOwnProperty("AllowRequestToJoinLeave")
? true
: false,name: props.Member.Title,members: (props.Member.Users?.results || []).map(function (member) {
return {
access: accessArr,email: member.Email,groupName: props.Member.Title,id: member.Id,isAdmin: member.IsSiteAdmin,title: member.Title,};
}),};
}
function _getRequest(props) {
return new Promise(function (resolve,reject) {
fetch(props.url + props.qs,{
method: "GET",headers: {
Accept: "application/json; odata=verbose","Content-type": "application/json; odata=verbose","X-RequestDigest": props.requestDigest,},})
.then(function (resp) {
return resp.json();
})
.then(resolve)
.catch(reject);
});
}
self.addEventListener("message",function (e) {
if (!e.data.data) {
var promise1 = _getRequest(Object.assign(e.data,{ qs: e.data.qs1 }));
var promise2 = _getRequest(Object.assign(e.data,{ qs: e.data.qs2 }));
Promise.all([promise1,promise2]).then(function ([data1,data2]) {
self.postMessage({
info: data2.d.results.map(formatSitesInfo),sites: data1.d.results.map(formatSites),url: e.data.url,});
});
}
});
解决方法
我最终制作了一个计时器,如果有另一个对工人的调用(发现另一个子站点有子站点),它将被重置。如果计时器停止,则意味着我们已到达站点的 childern 末尾。然后它转到下一个函数。会有一点延迟,但我可以忍受。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。