我有一個使用 Axios 下載 zip 檔案并將檔案解壓縮到臨時目錄的函式。該程序本身按預期作業,但在繼續之前我很難等待最終結果。我承認我并不完全理解如何使用 promise,但這正是我需要幫助學習的。
這是完整的代碼:
const axios = require('axios');
const StreamZip = require('node-stream-zip');
// Pipedream: steps.trigger.raw_event.body.result_set.download_links.json.all_pages
// Testing: https://api.countdownapi.com/download/results/04_NOVEMBER_2021/1900/Collection_Results_F4C0B671_51_All_Pages.zip
const all_pages = 'https://api.countdownapi.com/download/results/04_NOVEMBER_2021/1900/Collection_Results_F4C0B671_51_All_Pages.zip';
let fileName = 'all_pages.zip';
async function asyncFunc() {
return await axios.get(all_pages, {responseType: "stream"})
.then(res => {
console.log("Waiting ...")
if (res.status === 200) {
const path = require("path");
const SUB_FOLDER = "";
fileName = fileName || all_pages.split("/").pop();
const dir = path.resolve(__dirname, SUB_FOLDER, fileName);
res.data.pipe(fs.createWriteStream(dir));
res.data.on("end", () => {
console.log("Download Completed");
const zip = new StreamZip({
file: dir,
storeEntries: true
});
zip.on('error', function (err) {
console.error('[ERROR]', err);
});
zip.on('ready', function () {
console.log('All entries read: ' zip.entriesCount);
// console.log(zip.entries());
});
zip.on('entry', function (entry) {
const pathname = path.resolve('./tmp', entry.name);
if (/\.\./.test(path.relative('./tmp', pathname))) {
console.warn("[zip warn]: ignoring maliciously crafted paths in zip file:", entry.name);
return;
}
if ('/' === entry.name[entry.name.length - 1]) {
console.log('[DIR]', entry.name);
return;
}
console.log('[FILE]', entry.name);
zip.stream(entry.name, function (err, stream) {
if (err) {
console.error('Error:', err.toString());
return;
}
stream.on('error', function (err) {
console.log('[ERROR]', err);
});
// example: print contents to screen
// stream.pipe(process.stdout);
// example: save contents to file
fs.mkdir(path.dirname(pathname), {recursive: true}, function () {
stream.pipe(fs.createWriteStream(pathname));
}
);
});
});
});
} else {
console.log(`ERROR >> ${res.status}`);
}
})
.catch(err => {
console.log("Error ", err);
});
}
(async () => {
try {
await asyncFunc();
console.log('Finished')
} catch (error) {
console.error(error);
}
})();
正如我所說,代碼本身的作業原理是它會下載 zip 檔案并提取內容——但是,我的測驗 console.log('Finished') 會在 Axios 獲取后立即觸發。以下是操作順序的結果:
Waiting ...
Finished
Download Completed
[FILE] Collection_Results_F4C0B671_51_Page_1.json
[FILE] Collection_Results_F4C0B671_51_Page_2.json
[FILE] Collection_Results_F4C0B671_51_Page_3.json
[FILE] Collection_Results_F4C0B671_51_Page_4.json
[FILE] Collection_Results_F4C0B671_51_Page_5.json
[FILE] Collection_Results_F4C0B671_51_Page_6.json
[FILE] Collection_Results_F4C0B671_51_Page_7.json
All entries read: 7
請不要投反對票;如果我需要提供更多資訊,我會盡力而為。我嘗試閱讀有關 Promises 和類似問題的其他文章,但我嘗試了很多選擇,但都沒有成功。我在這個問題上花了四天時間,所以我真的需要幫助。*
uj5u.com熱心網友回復:
使用 Async/Await 的一個主要優點是您可以避免深度嵌套、難以閱讀的代碼 - 例如您的代碼。將此代碼分解為功能單元更有意義。與其認為所有這些代碼“必須在一起”,不如認為“分開時效果更好”。
所以入口點可以呼叫axios,用于.then()觸發資料檔案下載,用于.then()觸發解壓,用于then()觸發流寫入功能。
您使用 的回呼版本造成了困境StreamZip。如果您使用 Promise 版本的 API,它會簡化很多事情。
像下面這樣的東西更容易使操作順序合理化。
try {
console.log('Starting')
axios.get(all_pages, {responseType: "stream"})
.then(download)
.then(unzip)
.then(writeFile)
console.log('Finished')
} catch (error) {
console.error(error);
}
uj5u.com熱心網友回復:
如果您希望在讀取所有條目后顯示 Finished 陳述句,為什么不將其添加到代碼的這一部分?
zip.on('ready', function () {
console.log('All entries read: ' zip.entriesCount);
// console.log(zip.entries());
// ADD THE FINISHED STATEMENT HERE
});
編輯
根據檔案,您可以在流結束后執行以下操作。
const stm = await zip.stream('path/inside/zip.txt');
stm.on('end', () => {
zip.close();
// FINISHED AT THIS POINT ?
})
這是您可以說您已完成流式傳輸(已完成)的另一個地方。根據使用情況,您可能不必在此處關閉拉鏈。
uj5u.com熱心網友回復:
您可以簡單地回傳一個新的承諾,而不是axios.get下載完成時回傳的和解決的承諾,如下所示:
async function asyncFunc() {
return new Promise(function(resolve, reject){
axios.get(all_pages, {responseType: "stream"})
.then(res => {
console.log("Waiting ...")
//...
res.data.on("end", () => {
console.log("Download Completed");
// resolve the promise when download is finished
resolve();
轉載請註明出處,本文鏈接:https://www.uj5u.com/caozuo/351788.html
標籤:javascript 节点.js json
