问题
I want to build a simple playground with MEAN stack that mimics plunker: we have a list of files and a textarea on the left hand, and a live preview on the right hand. Note that the files are saved in a temporary folder, and the live preview is an iframe
injected by the files from that temporary folder.
I have coded something. In the front-end, the controller watches on modifications of files in the textarea; each time there is a change, render
will be called and it will send a $http.post
to save the new version of all the files.
app.controller('Ctrl', ['$scope', 'codeService', function ($scope, codeService) {
...
$scope.$watch('files', function () {
codeService.render($scope.files)
}, true);
}]);
app.service('codeService', ['$http', function ($http) {
this.render = function (files) {
...
var arrayLength = files.length;
for (var i = 0; i < arrayLength; i++) {
$http.post('/writeFile', files[i]);
}
}
}
In the back-end:
router.post('/writeFile', function (req, res, next) {
console.log("router.post /writeFile");
var file = req.body;
var fs = require('fs');
fs.writeFileSync("public/tmp/" + file.name, file.body);
});
My tests show that, for the first modification, it is indeed written to the files in the server. However, for consecutive modifications, the 2nd and following writing may take more than 20 seconds EACH.
Does anyone know what slows the writings (except for the 1st one)?
Additionally, should I call $http.post('/writeFile', files[i])
or write router.post('/writeFile'...
in an asynchronous way?
Edit 1:
I am also wondering if it is correct to write the http request in the following way (am I having an asynchronous function (ie, http post) inside a synchronous function (ie, render
)? Should I make render
asynchonous?):
app.service('codeService', ['$http', function ($http) {
this.render = function (files) {
...
var arrayLength = files.length;
for (var i = 0; i < arrayLength; i++) {
$http.post('/writeFile', files[i]);
}
}
}
When I see other http requests in my code, the fashion is often like
o.create = function (post) {
return $http.post('/posts', post, {
headers: { Authorization: 'Bearer ' + auth.getToken() }
}).success(function (data) {
o.posts.push(data)
});
};
回答1:
Your could try to refactor your code and include following things:
1) Wrap your watcher into debounce function.https://lodash.com/docs/4.17.4#debounce
$scope.$watch('files', _.debounce(function () {
codeService.render($scope.files)
}, 1000), true);
It prevents useless calls
2)Use writeFile
instead of writeFileSync
fs.writeFile("public/tmp/" + file.name, file.body, (err) => {
if (err) throw err;
console.log('It\'s saved!');
});
The power of NodeJs in async functions, try to avoid sync calls in your code.
来源:https://stackoverflow.com/questions/42364694/consecutive-writings-to-files-in-the-server-are-slow