【发布时间】:2021-07-02 10:56:58
【问题描述】:
我正在使用网络工作者以递归方式获取网站信息,包括其子网站(第 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,
qs1: "/_api/web/webinfos?$select=ServerRelativeUrl,Title",
qs2:
"/_api/Web/RoleAssignments?$expand=Member/Users,RoleDefinitionBindings",
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,
});
});
}
});
【问题讨论】:
-
这里有几个错误,
Promise.all返回一个承诺,你没有对这个承诺做任何事情,所以它是一个 NULL OP。第二个fetch返回一个promise,但你不要在_getRequest中返回它,无论如何在这里使用Promise 构造函数是一种反模式。 -
是的,它应该返回一个承诺。在进行第一次调用后,Promise.all() 将通过解析器 obj 的值。解析器 obj 看起来像这样 resolver = { site1: f(), site2; f()} 值等于解析。所以发现所有的值都是0“解决”它应该去下一个函数; thenable 是我的格式化函数
-
对于 fetch 承诺:因为它在 promise.all 中,所以它要么显示解决要么拒绝。我没有问题(不好的做法),但你应该可以这样写。
-
现在阅读构造函数反模式
-
据我所知,您从未将
resolver[e.data.url]设置为任何内容。你为一些整数设置了resolver[e.data.sites[i].url]i,你设置了resolver[baseUrl]你知道e.data.url是这些值之一吗?
标签: javascript rest recursion promise web-worker