我正在使用带有Node.js的Inquirer库,在使用promises时我仍然得到了厄运的金字塔,我做错了什么?
仅供参考,查询者库API基本上是:
inquirer.prompt([
question1,
question2,
question3,
...
questionX
]).then(function(answers){});
其中答案是哈希值,其中键代表每个问题。这里没什么不寻常的。
无论如何,使用API,我总是得到getAnswersToPrompts().then(function(answers){})
,并且将promises嵌套在前一个中似乎更方便......就像这样:
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的事情变得更加复杂
尽可能清楚,我肯定需要先前承诺的结果,但有时我需要之前的承诺结果,甚至是之前的结果。
嵌套函数允许我需要的数据在范围内,这要归功于闭包等。
答案 0 :(得分:6)
在调用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
。我认为嵌套函数有两到三个深度来容纳这个仍然是可读的,但你的另一个选择是在promise链之外定义一个变量,我在上面为pathsToRun
显示了这个变量。
最后,您的示例在整个promise链中使用了三个名为answers
的不同变量,这可能会增加混淆。一般来说,我认为使用相同的名称作为承诺回调结果是很好的,但为了清楚起见,我在这里重新命名了它们。
答案 1 :(得分:1)
//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
热潮!现在,您可以避免在顶部对变量进行笨拙的分配。如果你看不出它是如何工作的......请问我。