Передать значение в цепочке обещаний последующим обработчикам

Рассмотрим этот код:

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);

Обратите внимание, что обе функции sendMessage*() принимают сокет в качестве параметра. Но только первый получит это, потому что только первый получит разрешенное значение из openSocket().

Я могу обойти это, используя переменную во внешней области, т.е. назначить сокет после его разрешения, а затем использовать его в sendMessage2(), но это кажется немного хакерским и грязным.

Кроме того, я знаю, что могу использовать некоторую поддержку библиотек, как описано в этом ответе относительно Q.

Я ищу канонический способ разработки этого кода, который:

  • не требует никаких переменных во внешней области
  • не будет полагаться на сторонние библиотеки промисов (должны быть основаны на промисах ES6)

Есть ли способ сделать это? Или было бы лучше реорганизовать мой код, чтобы упростить его?


person kamituel    schedule 04.09.2014    source источник


Ответы (1)


Вы можете сделать это без использования сторонней библиотеки и беспорядка внешней области. Просто передайте аргумент следующему обещанию, как это

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) {}

А затем вызовите их, как вы сделали в вопросе

openSocket()
    .then(sendMessage1)
    .then(sendMessage2)
    .then(closeSocket)
    .catch(function(err) {
        console.error("Failed with error", err);
    });
person thefourtheye    schedule 04.09.2014
comment
Функция sendMessage1() должна разрешать ответ, а не сокет. Имея это в виду, как бы вы решили это? Разрешить карту/массив как с ответом, так и с сокетом? - person kamituel; 04.09.2014
comment
@kamituel О да, в этом случае вы можете просто разрешить массив, как я показал в обновленном ответе. - person thefourtheye; 04.09.2014