我有 2 段代碼 1) 由 2nd 呼叫以填充陣列并將其寫入檔案。
async function timeSeries(obj) {
data = [
{
original_value: []
}
]
//read file named as passed object's _id
await fs.readFile("./api/assignment_data/" obj._id ".json", "utf-8", function read(err, datas) {
if (err) {
throw err;
}
const filedata = JSON.parse(datas)
filedata.map(line => data[0].original_value.push(line.original_value))
})
setTimeout(() => {
try {
fs.writeFileSync("./api/timeseries.json", JSON.stringify(data), { encoding: 'utf8', flag: 'w' })
} catch (error) {
console.log(error)
}
}, 300);
}
問題是,在 fs.readfile 函式內部使用它后我無法訪問上面的全域資料陣列(回呼范圍地獄問題),我不得不 setTimeout 然后我可以使用另一個 fs.writeFileSync 函式將它寫入檔案中(如果我回傳陣列,我會得到一個承諾,我想要資料)。我該如何解決這個問題?而不是將它寫入另一個檔案并在另一個路由中使用它(下面)如何直接回傳第二個路由中的陣列并將其作為 json res 傳遞?
第 2 節)
router.route("/api/debug/:num").get((req, res) => {
fs.readFile("./api/assignment_data/metrics.json", "utf8", function read(err, data) {
if (err) {
console.log(err);
}
const objdata = JSON.parse(data)
timeSeries(objdata[req.params.num])
})
fs.readFile("./api/timeseries.json", "utf8", function read(err, data) {
if (err) {
console.log(err);
}
const objdata = JSON.parse(data)
res.json(data)
})
})
uj5u.com熱心網友回復:
如果您使用fs.readFile并希望在讀取檔案后執行操作,則必須在回呼函式中執行操作(在您的情況下寫入和讀取檔案)。此外,如果您可以同步讀取,則可以使用fs.readFileSync。
uj5u.com熱心網友回復:
首先,我們需要解釋一些事情:
fs.readFile()是非阻塞和異步的。這意味著當您呼叫它時,它會啟動操作,然后立即回傳并開始執行緊隨其后的代碼。然后,一段時間后,它呼叫它的回呼。
所以,你的代碼是:
- 打電話
fs.readFile() - 然后,立即設定一個計時器
- 然后,這是
fs.readFile()回呼和計時器之間不確定的競賽,以查看誰先完成。如果計時器首先完成,那么它將呼叫它的回呼,并且您將嘗試data在它被填充之前訪問(因為fs.readFile()回呼尚未被呼叫)。
您無法以這種方式撰寫可靠的代碼,因為您正在猜測不確定的異步操作的時間。相反,您必須在回呼中使用異步結果,因為這是您知道完成時間以及有效時間的唯一地方。因此,解決您的問題的一種方法是鏈接異步操作,以便將第二個操作放在第一個的回呼中:
function timeSeries(obj, callback) {
//read file named as passed object's _id
fs.readFile("./api/assignment_data/" obj._id ".json", "utf-8", function read(err, datas) {
if (err) {
console.log(err);
// tell caller about our error
callback(err)
return;
} else {
let data = [{original_value: []}];
const filedata = JSON.parse(datas);
for (let line of filedata) {
data[0].original_value.push(line.original_value);
}
fs.writeFile("./api/timeseries.json", JSON.stringify(data), { encoding: 'utf8' }, (err) => {
if (err) {
console.log(err);
callback(err);
return;
} else {
// give our data to the caller
callback(data);
}
});
}
})
}
然后,要呼叫此函式,您需要向它傳遞一個回呼,在回呼中您可以看到錯誤或獲取資料。
在現代 nodejs 中,它更容易使用,async/await并且fs模塊中基于Promise的介面:
const fsp = require('fs').promises;
async function timeSeries(obj) {
//read file named as passed object's _id
try {
let datas = await fsp.readFile("./api/assignment_data/" obj._id ".json", "utf-8");
const filedata = JSON.parse(datas);
let data = [{original_value: []}];
for (let line of filedata) {
data[0].original_value.push(line.original_value);
}
await fsp.writeFile("./api/timeseries.json", JSON.stringify(data), { encoding: 'utf8' });
return data;
} catch(e) {
console.log(e);
// handle error here or throw back to the caller
throw e;
}
}
對于此版本,呼叫者可以使用await和try/catch獲取錯誤:
try {
let data = await timeSeries(obj);
// do something with data here
} catch(e) {
// handle error here
}
uj5u.com熱心網友回復:
根據您撰寫的代碼,我可以使用簡單的 async-await 對其進行修改-希望這會有所幫助
import fs from 'fs'
async function timeSeries(obj) {
const data = [{
original_value: []
}]
const assData = fs.readFileSync('./api/assignment_data/metrics.json', 'utf8')
const filedata = JSON.parse(assData)
filedata.map(line => data[0].original_value.push(line.original_value))
// no need for timeOut
fs.writeFileSync('./api/timeseries.json', JSON.stringify(data));
//return data if u need
return data
}
router.route("/api/debug/:num").get(async (req, res) => {
try {
const metricData = fs.readFileSync('./api/assignment_data/metrics.json', 'utf8')
const objdata = JSON.parse(data)
const timeSeriesData = await timeSeries(objdata[req.params.num])
// returning TimeSeriesData
res.status(200).json(timeSeriesData)
})
}
catch (error) {
res.status(500).send(error.message)
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/322892.html
標籤:javascript 节点.js 表达 承诺
