将 JS 承诺包装成一个函数
Wrapping JS promisies into a function
我有一个 Web 应用程序,它从 URLs 收集各种文件并将它们放在 zip 存档中。
我正在使用 JSZip 来处理 zip 文件。这是一个代码示例,其中包含位于同一服务器上的另一个 zip 存档的内容:
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
<script type="text/javascript" src="./js/jszip.js"></script>
<script type="text/javascript" src="./js/jszip-utils.js"></script>
<script type="text/javascript" src="./js/FileSaver.js"></script>
Downloading archive with contents from another archive
<script>
jQuery(function($) {
var zip = new JSZip();
zip.file('see.txt','Regular files are being included with a single function call');
function flash(){
JSZipUtils.getBinaryContent('/version.zip', function(err, data) {
try {
zip.loadAsync(data)
.then(function(zip) {
zip.generateAsync({type: 'blob'},
function(metadata) {
})
.then(function(blob) {
saveAs(blob, 'result.zip');
}, function(e) {
showError(e);
});
})
.then(function success() {
});
} catch(e) {console.log(e)}
});
};
flash();
return false;
});
</script>
Working JSFiddle with libs and examples included
它工作得很好。 JSZipUtils.getBinaryContent
returns 来自 URL 的 zip 文件的二进制内容的承诺。 zip.loadAsync()
读取二进制内容并将其包含到存档中。 zip.generateAsync
在 RAM 中构建 zip 存档的表示,以便我们稍后下载。
但是,我需要将 zip.loadAsync()
包装成一个我可以多次调用的函数。我试过这样的事情:
function zipmerge(source){
JSZipUtils.getBinaryContent(source, function (err, data) {
if(err) {
throw err; // or handle the error
}
var zip = new JSZip();
zip.loadAsync(data);
});
};
但看起来 zip.loadAsync()
需要等待才能完成。如果我只是 运行 上面的函数然后生成一个 zip 文件,它只会忽略我试图包含的 zip 文件的内容。
我不太了解 promise 的工作方式,所以我需要一个函数的帮助,该函数将接收 url 并等待 promise 解决,以便我可以多次调用它以及常规zip.file
然后触发 zip 生成。谢谢。
您可以将 JSZipUtils.getBinaryContent
方法包装在 Promise 中并生成它们的数组。然后,您可以使用 Promise.all()
创建一个新的承诺,该承诺会在数组中的所有承诺都已解决时解决。
这是我将如何做的一个例子:
// function to read in a list of source zip files and return a merged archive
function mergeZips(sources) {
var zip = new JSZip();
return readSources(sources, zip)
.then(function() {
return zip;
});
}
// generate an array of promises for each zip we're reading in and combine them
// into a single promise with Promise.all()
function readSources(files, zip) {
return Promise.all(
files.map(function(file){
return readSource(file, zip);
})
);
}
// promise-ified wrapper function to read & load a zip
function readSource(file, zip) {
return new Promise(function(resolve, reject) {
JSZipUtils.getBinaryContent(file, function (err, data) {
if (err) {
reject(err);
}
// resolving the promise with another promise will pass the promise
// down the chain:
resolve(zip.loadAsync(data));
});
});
}
// example usage:
mergeZips([
'file1.zip',
'file2.zip',
'file3.zip'
]).then(function(zip) {
zip.generateAsync({type: 'blob'})
.then(function(blob){
saveAs(blob, 'result.zip')
})
});
我有一个 Web 应用程序,它从 URLs 收集各种文件并将它们放在 zip 存档中。
我正在使用 JSZip 来处理 zip 文件。这是一个代码示例,其中包含位于同一服务器上的另一个 zip 存档的内容:
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
<script type="text/javascript" src="./js/jszip.js"></script>
<script type="text/javascript" src="./js/jszip-utils.js"></script>
<script type="text/javascript" src="./js/FileSaver.js"></script>
Downloading archive with contents from another archive
<script>
jQuery(function($) {
var zip = new JSZip();
zip.file('see.txt','Regular files are being included with a single function call');
function flash(){
JSZipUtils.getBinaryContent('/version.zip', function(err, data) {
try {
zip.loadAsync(data)
.then(function(zip) {
zip.generateAsync({type: 'blob'},
function(metadata) {
})
.then(function(blob) {
saveAs(blob, 'result.zip');
}, function(e) {
showError(e);
});
})
.then(function success() {
});
} catch(e) {console.log(e)}
});
};
flash();
return false;
});
</script>
Working JSFiddle with libs and examples included
它工作得很好。 JSZipUtils.getBinaryContent
returns 来自 URL 的 zip 文件的二进制内容的承诺。 zip.loadAsync()
读取二进制内容并将其包含到存档中。 zip.generateAsync
在 RAM 中构建 zip 存档的表示,以便我们稍后下载。
但是,我需要将 zip.loadAsync()
包装成一个我可以多次调用的函数。我试过这样的事情:
function zipmerge(source){
JSZipUtils.getBinaryContent(source, function (err, data) {
if(err) {
throw err; // or handle the error
}
var zip = new JSZip();
zip.loadAsync(data);
});
};
但看起来 zip.loadAsync()
需要等待才能完成。如果我只是 运行 上面的函数然后生成一个 zip 文件,它只会忽略我试图包含的 zip 文件的内容。
我不太了解 promise 的工作方式,所以我需要一个函数的帮助,该函数将接收 url 并等待 promise 解决,以便我可以多次调用它以及常规zip.file
然后触发 zip 生成。谢谢。
您可以将 JSZipUtils.getBinaryContent
方法包装在 Promise 中并生成它们的数组。然后,您可以使用 Promise.all()
创建一个新的承诺,该承诺会在数组中的所有承诺都已解决时解决。
这是我将如何做的一个例子:
// function to read in a list of source zip files and return a merged archive
function mergeZips(sources) {
var zip = new JSZip();
return readSources(sources, zip)
.then(function() {
return zip;
});
}
// generate an array of promises for each zip we're reading in and combine them
// into a single promise with Promise.all()
function readSources(files, zip) {
return Promise.all(
files.map(function(file){
return readSource(file, zip);
})
);
}
// promise-ified wrapper function to read & load a zip
function readSource(file, zip) {
return new Promise(function(resolve, reject) {
JSZipUtils.getBinaryContent(file, function (err, data) {
if (err) {
reject(err);
}
// resolving the promise with another promise will pass the promise
// down the chain:
resolve(zip.loadAsync(data));
});
});
}
// example usage:
mergeZips([
'file1.zip',
'file2.zip',
'file3.zip'
]).then(function(zip) {
zip.generateAsync({type: 'blob'})
.then(function(blob){
saveAs(blob, 'result.zip')
})
});