Цепочка promises с q.js

Я пытаюсь понять, как работает цепочка ссылок. Я использую q.js. Здесь я играю.

var Q = require("q"); // npm install q

// the function Q(value) returns a fulfilled promise with the value... I think.
Q(1).then(Q(2)).then(Q(3)).then(Q(4)).then(function(n) {
    console.log(n);
});

Q(1).then(function(n) {
    return Q(2);
}).then(function(n) {
    return Q(3);
}).then(function(n) {
    return Q(4);
}).then(function(n) {
    console.log("done: " + n);
});

Мой вопрос в основном сводится к тому, почему первый log 1, в то время как последний регистрирует то, что я ожидаю, и в основном журналы с 1 по 4. Я надеялся, что первый из них будет записывать 4 вместо 1.

Я действительно просто хотел иметь некоторые методы, которые возвращают promises, а затем объединяют их вместе в водопад, как мода - я думаю, я мог бы использовать async и водопад, но просто хотел знать, может ли это быть достигнуто w/ promises.

Ответ 1

Это потому, что then не ожидает другого обещания в качестве аргумента. Скорее, он ожидает функций обработчика, обратного вызова и/или ошибочного сообщения, которое вы передаете во втором примере. Действительно, любой аргумент, который не является функцией, просто игнорируется.

Из документов:

Если вы вернете значение в обработчике, outputPromise будет выполнен.

Если вы выбрали исключение в обработчике, outputPromise будет отклонен.

Если вы вернете обещание в обработчике, outputPromise "станет" этим обещанием. Возможность стать новым обещанием полезна для управления задержками, объединения результатов или восстановления от ошибок.

Итак, да, цепочка promises может быть выполнена. Вы делаете это правильно во втором примере.

Возможно, что надуманный пример прохождения пройденного promises делает способ работы цепочки promises показаться чрезмерно подробным, но в реальном мире вы обычно связываете promises, потому что вас интересуют их возвращаемые значения, например:

somethingAsync().then(function (n) {
  return somethingElseAsync(n);
})
.then(function (n) {
  return somethingElseAsync(n);
})
.then(function (result) {
  // ...
})

(На самом деле это зеркалирует async.waterfall. Если вы просто хотели вызвать серию асинхронных функций, чтобы не отнестись к их результатам, вы можете использовать async.series)

Ответ 2

Я знаю, что javascript не имеет статических типов, но вам нужно подумать о типах здесь.

Q(1);                             // has type Promise[Int]
function (n) { return Q(2); }     // has type Int => Promise[Int]

Q.then требуется вторая.