在使用诺言的时候,我还是得到厄运的金字塔,我做错了什么?

我正在使用Node.js的Inquirer库,在使用Promise时,我仍然得到厄运的金字塔,我做错了什么?

查询器库API基本上是:

inquirer.prompt([ question1, question2, question3, ... questionX ]).then(function(answers){}); 

答案是散列,代表每个问题的键。 这里没有什么特别的。

无论如何,使用API​​,我总是得到getAnswersToPrompts().then(function(answers){}) ,保持嵌套在前面的承诺似乎更方便…像这样:

 function run (rootDir) { return watchHelper().then(function (answers) { return chooseDirs({ allowDirs: answers.allow, originalRootDir: rootDir, onlyOneFile: false }).then(function (pathsToRun) { assert(pathsToRun.length > 0, ' You need to select at least one path.'); return getOptions(availableOptionsForPlainNode).then(function (answers) { const selectedOpts = answers[ 'command-line-options' ]; return localOrGlobal().then(function (answers) { const sumanExec = answers.localOrGlobal; console.log(' => ', colors.magenta.bold([ '$', sumanExec, '--watch', pathsToRun, selectedOpts ].join(' '))); }); }); }); }).catch(rejectionHandler); } 

我可以这样做:

 function run(){ return makePromise() .then(fn1(data1)) .then(fn2(data2)) .then(fn3(data3)) } 

其中fn1,fn2,fn3如下所示:

 function fnX(data){ return function(answers){ return promise(data); } } 

但是这使得AFAICT理解变得更加复杂

只要尽可能清楚,我肯定需要前一个承诺的结果,但有时候我需要从承诺之前的结果,甚至之前的结果。

嵌套的function允许我需要在范围内的数据,由于封闭等

then 调用之前返回下一个Promise:

 function run (rootDir) { var pathsToRun; return watchHelper() .then(function (watchHelperAnswers) { return chooseDirs({ allowDirs: watchHelperAnswers.allow, originalRootDir: rootDir, onlyOneFile: false }); }).then(function (chooseDirsResult) { assert(chooseDirsResult.length > 0, ' You need to select at least one path.'); pathsToRun = chooseDirsResult; return getOptions(availableOptionsForPlainNode); }).then(function (getOptionsAnswers) { const selectedOpts = getOptionsAnswers[ 'command-line-options' ]; return localOrGlobal(); }).then(function (localOrGlobalAnswers) { const sumanExec = localOrGlobalAnswers.localOrGlobal; console.log(' => ', colors.magenta.bold([ '$', sumanExec, '--watch', pathsToRun, selectedOpts ].join(' '))); }).catch(rejectionHandler); } 

但是有时我需要在此之前的承诺的结果,甚至在此之前的结果

在你的例子中唯一的例子是pathsToRun 。 我认为嵌套函数两三个深,以适应这个仍然是可读的,但你的另一个select是定义一个variables之外的承诺链,我已经显示在上面的pathsToRun

最后,你的例子使用了三个不同的variables,在整个承诺链中都调用了answers ,这可能会增加混淆。 一般来说,我认为可以使用相同的名称来保证callback结果,但为了清晰起见,我在这里重新命名了这个答案。

乔·戴利的答案接近完美,但要补充一点。 我真的不喜欢这个函数顶部的variables。 我从来不喜欢它与async.waterfall / async.series …我不喜欢承诺…以下模式应该避免这一点。 我们在每个promisecallback中累积数据,然后在最后的promisecallback中获得所有的数据。

 //start function run (rootDir) { return watchHelper().then(function (watchHelperAnswers) { return chooseDirs({ allowDirs: watchHelperAnswers.allow, originalRootDir: rootDir, onlyOneFile: false }); }).then(function (chooseDirsResult) { return getOptions(availableOptions).then(function(options){ return { //accumulate answers options: options, pathsToRun: chooseDirsResult } }); }).then(function (obj) { return localOrGlobal().then(function(answers){ return Object.assign(obj,{ //accumulate answers localOrGlobal: answers.localOrGlobal }); }); }).then(function (obj) { const {...allTheAnswers} = obj; }).catch(rejectionHandler); } //end 

繁荣! 现在,您可以避免对顶部variables的尴尬分配。 如果你不明白这是如何工作的…问我。