Javascript 如何使用q创建回调链?

Javascript 如何使用q创建回调链?,javascript,asynchronous,callback,promise,q,Javascript,Asynchronous,Callback,Promise,Q,我在理解如何使用“q”时遇到了一些问题(https://github.com/kriskowal/q)javascript的承诺库: var delayOne = function() { setTimeout(function() { return 'hi'; }, 100); }; var delayTwo = function(preValue) { setTimeout(function() { return preValue +

我在理解如何使用“q”时遇到了一些问题(https://github.com/kriskowal/q)javascript的承诺库:

var delayOne = function() {
    setTimeout(function() {
        return 'hi';
    }, 100);
};

var delayTwo = function(preValue) {
    setTimeout(function() {
        return preValue + ' my name';
    }, 200);
};

var delayThree = function(preValue) {
    setTimeout(function() {
        return preValue + ' is bodo';
    }, 300);
};

var delayFour = function(preValue) {
    setTimeout(function() {
        console.log(preValue);
    }, 400);

};

Q.fcall(delayOne).then(delayTwo).then(delayThree).then(delayFour).end();
这只返回未定义的…

之所以得到“未定义”,是因为链接的函数没有返回任何内容:

var delayOne = function() {
  setTimeout(function() {
    return 'hi';
  }, 100);
};
delayOne
调用
setTimeout
,但不返回任何内容(
undefined

要实现您的目标,您必须使用
Q.defer

var delayOne = function() {
  var d = Q.defer();    
  setTimeout(function() {
    d.resolve("HELLO");
  }, 100);
  return d.promise;
};

var delayTwo = function(preValue) {
   setTimeout(function() {
     alert(preValue);
   }, 
   400);
};

delayOne().then ( delayTwo );

正如Wronisty所指出的,您需要从这些函数中的每一个返回承诺,但是您还应该尽可能抽象任何面向回调的API(如
setTimeout
),并使用返回承诺的API

setTimeout
的情况下,Q已经提供了
Q.delay(ms)
,它返回的承诺将在指定的毫秒数后得到解决,非常适合替换
setTimeout

var delayOne = function() {
    return Q.delay(100).then(function() {
        return 'hi';
    });
};

var delayTwo = function(preValue) {
    return Q.delay(200).then(function() {
        return preValue + ' my name';
    });
};

var delayThree = function(preValue) {
    return Q.delay(300).then(function() {
        return preValue + ' is bodo';
    });
};

var delayFour = function(preValue) {
    return Q.delay(400).then(function() {
        console.log(preValue);
    });
};

Q.fcall(delayOne).then(delayTwo).then(delayThree).then(delayFour).done();

(注意:
end
已替换为
done

谢谢您的解决方案。除此之外,我还必须做出决定,如果我使用Q,那么会大大提高代码质量,而另一方面,它会导致硬依赖。如果你遇到这个问题,你有经验吗?如果你使用很多链式异步调用,那么你需要一些库来逃避“末日金字塔”:)。我个人更喜欢asyncjs:,并且在一些中型项目中成功地使用了它。