0

I'm working with Loopback and I want to create an uploading interface which logs the number of uploads. I'm using an own model together with the storage component.

I am using the storage component's upload-function and I want to update the object attribute 'uploadedPictures' after the upload has been successful (see code below). I have the problem, that I don't know how to use 'this'-reference after an asynchronous method in a safe way. E.g. if there are many calls on my function, the attribute counts up just once.

module.exports = function(Upload) {
    Upload.prototype.upload = function(ctx, options, cb) {
        if (!options)
            options = {};
        ctx.req.params.container = 'common';        

        // starting the upload and wait for the result
        var promise = new Promise(function(resolve, reject) {
            Upload.app.models.container.upload(ctx.req, ctx.result, options, function(err, fileObj) {
                if (err) {
                    console.error('error occured during upload');
                    cb(err);
                }
                else {
                    var fileInfo = fileObj.files.file[0];
                    resolve(fileInfo);
                }
            });
        });
        var uploadObject = this; // not safe, but how should I do it?
        // count 'uploadedPictures' up, but only if upload was successful
        promise.then(function(fileInfo) {
            uploadObject.uploadedPictures++;
            uploadObject.save();
        })
        .catch(function(e) {
            console.error('error: '+e);
        });
        cb(null, this);
    };

    Upload.remoteMethod('upload', {
        description : 'Uploads a file',
        accepts : [ {
            arg : 'ctx',
            type : 'object',
            http : {
                source : 'context'
            }
        }, {
            arg : 'options',
            type : 'object',
            http : {
                source : 'query'
            }
        } ],
        returns : {
            arg : 'fileObject',
            type : 'object',
            root : true
        },
        isStatic : false,
        http : {
            verb : 'post'
        }
    });
};
Milgo
  • 2,617
  • 4
  • 22
  • 37

1 Answers1

1

Well, I found a dirty solution, but it works. I search the object itself with 'findById'.

Upload.prototype.upload = function(ctx, options, cb) {
    if (!options)
        options = {};
    ctx.req.params.container = 'common';

    var _this = this;       
    Upload.app.models.container.upload(ctx.req, ctx.result, options, function(err, fileObj) {
        try {
            var files = fileObj.files.file;
            console.log('upload success): '+JSON.stringify(files));
            if (files.length > 0) {
                Upload.findById(_this.id, function(err, res) {
                    res.onUploadSuccess(cb);
                });
            }
            else {
                cb(null, _this);
            }
        }
        catch (err) {
            console.error('WARN: Upload not successful: ' + err);
            cb(err, null);
        }
    });
};

Upload.prototype.onUploadSuccess = function(cb) {
    this.uploadedPictures++;
    this.save();
    cb(null, this);
}
Milgo
  • 2,617
  • 4
  • 22
  • 37