Javascript 在一个房间里等待承诺
我对承诺不熟悉。我知道一个人是怎么工作的 我有一个函数,可以将包含外部引用(图像、样式、脚本)的html文档转换为嵌入这些资源的文件。它需要从异步源(JSZip实例)读取资源 我希望函数仅在所有承诺Javascript 在一个房间里等待承诺,javascript,asynchronous,promise,jszip,Javascript,Asynchronous,Promise,Jszip,我对承诺不熟悉。我知道一个人是怎么工作的 我有一个函数,可以将包含外部引用(图像、样式、脚本)的html文档转换为嵌入这些资源的文件。它需要从异步源(JSZip实例)读取资源 我希望函数仅在所有承诺zip.file().async()之后返回。然后(…)被解析。例如,创建一个domDocument,然后对其执行一系列异步步骤,然后选择修改后的domDocument。可以修改调用此函数的区域以使用然后(例如处理文件(文件夹、zip、节点、dom)。然后(函数(结果)…如果需要) // folder
zip.file().async()之后返回。然后(…)
被解析。例如,创建一个domDocument
,然后对其执行一系列异步步骤,然后选择修改后的domDocument
。可以修改调用此函数的区域以使用然后
(例如处理文件(文件夹、zip、节点、dom)。然后(函数(结果)
…如果需要)
// folder is set elsewhere
// zipObject is a JSZip instance
// node is an xml document which contains path references to files mentioned in the html
// domDocument is a DOMParser instance which is the html file
// these are the queryselectors for elements I want to match and replace in the html
[
{"selector":"script[src]:not([src*='//'])","attribute":"src","type":"string"},
{"selector":"link[href$='.css']:not([href*='//'])","attribute":"href","type":"string"},
{"selector":"img:not([src*='//'])","attribute":"src","type":"base64"},
{"selector":"a[target='_blank']:not([href*='://'])","type":"link"}
].forEach(function(element) {
// grab all instances of a particular selector
[].forEach.call(domDocument.querySelectorAll(element.selector), function(instance) {
if (element.type === "link") { // replace link with plain text
var tNode = document.createTextNode(instance.textContent);
instance.parentNode.replaceChild(tNode, instance);
} else { // need to load from the linked document
var value = unescape(instance.getAttribute(element.attribute)),
path = null;
// images that are already encoded can be ignored
if (element.type==="base64" && (-1!==value.indexOf("data:image"))) return;
if (value.indexOf("../")==0) { // resolve dependancy filename
var dep = node.parentNode.querySelector("dependency");
if (null !== dep) {
var ref = node.parentNode.parentNode.querySelector("resource[identifier='" + dep.getAttribute("identifierref") + "']");
if (null !== ref) {
path = ref.querySelector("file[href]").getAttribute("href");
}
}
} else { // resolve path from filename
path = folder + value;
}
// perform the (asynchronous) modification of the document
zipObject.file(path).async(element.type).then(function success(content) {
if (element.attribute === "href") {
// <link href="file.css"> ==> <style>(file contents)</style>
var style = document.createElement("style");
style.appendChild(document.createTextNode(content));
instance.parentNode.replaceChild(style,instance);
} else if (element.type === "base64") {
// <img src="file.gif"> ==> <img src="data:image/gif;base64,(image-contents)">
var extn = value.substr(value.lastIndexOf(".") + 1).toLowerCase();
instance.setAttribute("src", "data:image/" + extn + ";base64," + content);
} else {
// <sript src="file.js"></script> => <script>(file-contents</script>)
instance.removeAttribute(element.attribute);
instance.appendChild(document.createTextNode(content));
}
}, function error (e) {
console.log("ConvertZipForHtml Error", e);
// leave it alone I guess
});
}
});
});
// want this to return the MODIFIED version of the string
return domDocument;
仍然掌握async和Promission中的概念@Bergi我真的看不出如何将链接上的代码合并到我的问题中。简而言之:收集在数组中的循环体中创建的所有承诺,然后调用
Promise。所有这些承诺都
。在我的例子中,承诺是从zip.aft中加载文件的输出呃加载内容后,它会替换外部循环中引用的元素。我如何在promise.all中引用这些变量?正如Bergi所说,使用promise.all会等待promise数组的所有成员都被解析或拒绝,在这种情况下,它会返回一个错误,您需要catch@Bergi我可以“我真的不知道如何将链接上的代码与我的问题结合起来。简言之:收集在数组中循环体中创建的所有承诺,然后调用Promise。所有这些承诺都是。在我的情况下,承诺是从zip中加载文件的输出。加载内容后,它会替换引用的元素。”在外部循环中。我如何在promise.all中引用这些变量?正如Bergi所说,使用promise.all将等待promise数组的所有成员被解析或拒绝,在这种情况下,它将返回一个您需要捕获的错误
function myFunction(args) {
function replaceElements(elements) {
return Promise.all(elements.map(selectElements));
}
function selectElements(element) {
return new Promise(function (resolve, reject) {
var myNodeList = domDocument.querySelectorAll(element.selector);
for (var i = myNodeList.length; i--;) { // (generally is faster than forwards!)
var instance = myNodeList[i];
// -- snip --
zipObject.file(path).async(element.type).then(function success(content) {
// -- snip --
resolve(instance);
})
}
});
}
return replaceElements([
{"selector":"script[src]:not([src*='//'])", "attribute":"src", "type":"string"},
{"selector":"link[href$='.css']:not([href*='//'])", "attribute":"href", "type":"string"},
{"selector":"img:not([src*='//'])", "attribute":"src", "type":"base64"},
{"selector":"a[target='_blank']:not([href*='://'])", "type":"link"}
]);
}