Consecutive writings to files in the server are sl

2019-07-26 23:43发布

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.

enter image description here

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条回答
萌系小妹纸
2楼-- · 2019-07-27 00:21

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.

查看更多
登录 后发表回答