2

Consider this code:

function openSocket() { /* returns a promise for a socket  */ }
function sendMessage1(socket) { /* sends 1st message, returns a promise for a response */ }
function sendMessage2(socket) { /* sends 2nd message, returns a promise for a response */ }
function cleanup(socket) { /* closes the socket */ }

function updateUI() {}
function showError(error) {}

openSocket()
    .then(sendMessage1)
    .then(sendMessage2)
    .then(cleanup)
    .then(updateUI)
    .catch(showError);

Note that both sendMessage*() functions accept socket as a parameter. But only first one will get this, because only the first one will get the resolved value from openSocket().

I can go around this by using a variable in the outer scope, i.e. assign the socket once it's resolved, and then use it in sendMessage2(), but it seems a bit hacky and dirty.

Also, I know I can use some library support, like described in this answer regarding Q.

I'm looking for a canonical way of designing this code, which:

  • would not require any variables in outer scope
  • would not rely on 3rd party promise libraries (should be based on ES6 promises)

Is there some way to accomplish that? Or would that be better to refactor my code to make it easier?

Community
  • 1
  • 1
kamituel
  • 34,606
  • 6
  • 81
  • 98

1 Answers1

2

You can do this without using a third party library and outer scope mess. Simply, pass the argument to the next promise like this

function openSocket() {
    return new Promise(function(resolved, failed) {
        if (Socket creation successful) {
            resolved(socket);
        } else {
            failed(error message);
        }
    });
}

function sendMessage1(socket) {
    // Actually send the message 1
    return new Promise(function(resolved, failed) {
        if (Message sent successfully) {
            resolved([socket, message]);
        } else {
            failed(error message);
        }
    });
}

function sendMessage2(parameters) {
    var socket = parameters[0], message = parameters[1];
    // Actually send the message 2
    return new Promise(function(resolved) {
        if (Message sent successfully) {
            resolved(socket);
        } else {
            failed(error message);
        }
    });
}

function closeSocket(socket) {}

And then invoke them like you did in the question

openSocket()
    .then(sendMessage1)
    .then(sendMessage2)
    .then(closeSocket)
    .catch(function(err) {
        console.error("Failed with error", err);
    });
thefourtheye
  • 233,700
  • 52
  • 457
  • 497
  • The `sendMessage1()` function should resolve to the response, not the socket. Having that in mind, how would you solve this? Resolve to a map/array with both the response, and socket? – kamituel Sep 04 '14 at 08:00
  • @kamituel Oh yeah, in that case, you can simply resolve with an array, like I have shown in the updated answer. – thefourtheye Sep 04 '14 at 08:03