Search code examples
javascriptangularjssocket.iopromiseangularjs-service

Wrap socket.on as a promise


I am making a service, with a function init as resolve. First, it creates a folder with the id of the connection, then it writes some default files inside. The folder (ie, the id of the connection) should be recorded, which is the purpose of this.dir.

The following code calls well initDir. However, it does not call initFiles (ie, alert("here") is not called). I guess it is because initDir was not made well as a promise.

Does anyone know how to amend it?

this.files = [ ... ... ];

this.dir = "public/tmp/default/";

this.initDir = function () {
    var socket = io.connect();
    return socket.on('id', function (id) {
        var dir = "public/tmp/" + id + "/";
        return $http.post('mkdir', { dir: dir })
            .then(function () {
                this.dir = dir;
            })
    })
} 

this.initFiles = function (dir, files) {
    return $http.post('writeFile', { dir: dir, file: files[0] })
        .then(function (res) {
            $http.post('writeFile', { dir: dir, file: files[1] })
                .then(function (res) {
                    console.log("saved 2 files")
                })
            })
    })
}

this.init = function () {
    return this.initDir() 
        .then(function (res) {
            alert("here");
            this.initFiles(this.dir, this.files)
        })
}

On the server side, it just sends the connection id after every connection:

io.sockets.on('connection', function (socket) {
    socket.emit('id', socket.id);
}

Edit 1: Following the answer of @epiqueras , I modified the code. The following code calls inside init, however it does not call inside initDir....

var dirP = "public/tmp/default/";

this.initDir = function () {
    return new Promise(function (resolve, reject) {
        alert("inside initDir")
        var socket = io.connect();
        socket.on('id', function (id) {
            var dir = "public/tmp/" + id + "/";
            $http.post('mkdir', { dir: dir })
                .then(function () {
                    dirP = dir;
                    resolve(dirP)
                })
        })
    })      
} 

this.init = function (files) {
    alert("inside init");
    return initDir
        .then(function (dir) {
            alert("before initFiles");
            this.initFiles(dir, files)
        })
}

Edit 2: after changing initDir.then to this.initDir().then, I have the following code. It shows well inside init, inside initDir, before initFiles. However, it does not show inside initFiles or write files.

this.initDir = function () {
    return new Promise(function (resolve, reject) {
        console.log("inside initDir")
        var socket = io.connect();
        socket.on('id', function (id) {
            var dir = "public/tmp/" + id + "/";
            $http.post('mkdir', { dir: dir })
                .then(function () {
                    dirP = dir;
                    resolve(dirP)
                })
        })
    })      
}; 

this.initFiles = function (dir, files) {
    console.log("initFiles: " + dir);
    return $http.post('writeFile', { dir: dir, file: files[0] })
        .then(function (res) {
            $http.post('writeFile', { dir: dir, file: files[1] })
                .then(function (res) {
                    console.log("saved 2 files")
                })
            })
    })
}

this.init = function (files) {
    console.log("inside init");
    return this.initDir().then(function (dir) {
        console.log("before initFiles " + dir + JSON.stringify(files));
        this.initFiles(dir, files)
    })
};

Solution

  • It's not working because socket.on does not return it's callback's return value.

    Try wrapping the code with a promise and resolve inside the callback instead of just returning.

    initDir() {
        return new Promise(function(resolve, reject) {
            socket.on.....
                $http.post.....then(resolve)
        }
    }
    

    Make sure you are returning the new Promise and that you are resolving the final value you wish to wait for.