大家好,我是nodejs的新手,我正在努力学习promise。我正在尝试实现一种菜单,它将根据用户输入执行某些功能。这是我正在使用的代码:
var q = require('q');
var readline = require('readline-sync');
function createNewPreset(){
var deferred = q.defer();
var preset = {
"name" : undefined,
"unit" : undefined,
"interval" : undefined,
"files" : [],
}
deferred.resolve(preset);
return deferred.promise;
}
function addPreset(){
console.log("adding");
var deferred = q.defer();
createNewPreset()
.then(function(){
console.log("Gettind input in addPreset");
})
.then(getUserInput)
.then(function(data){
console.log("Adding data" + data);
});
}
function getUserInput(){
var deferred = q.defer();
var stdin = process.stdin;
stdin.resume();
stdin.once('data', function(data){
data = data.toString().trim()
if(data.length > 20){
var err = new Error("The entered preset name is too long");
deferred.reject(err);
}
else{
deferred.resolve(data);
}
});
return deferred.promise;
}
function processChoice(input){
var deferred = q.defer();
var error = undefined;
var func;
switch(input){
case "a":
func = addPreset;
break;
case "q":
func = function(){
process.exit();
}
break;
default:
error = new Error("Invalid menu option entered.");
deferred.reject(error);
break;
}
deferred.resolve(func);
return deferred.promise;
}
function prompt(){
var stdout = process.stdout;
//indicates that prompt is being executed
stdout.write("(tic): ");
console.log("Waiting for input");
getUserInput()
.then(processChoice)
.then(function(func){ func(); })
.catch(function(err) {console.log(err)})
.then(prompt);
}
prompt();
我认为问题出在getUserInput()
和addPreset()
以及事件侦听器上。我希望只有在事件监听器被激活后,承诺链才能继续,但老实说,我不知道如何做到这一点。
以下是我的结果:
(tic): Waiting for input
a
adding
Gettind input in addPreset
(tic): Waiting for input
A
Adding dataA
[Error: Invalid menu option entered.]
(tic): Waiting for input
我想让链在事件侦听器上等待执行,然后再继续。有什么办法可以做到这一点吗?
您的代码中有一些错误
无特定顺序的
.then(function(func){ func(); })
应该是.then(function(func){ return func(); })
,因为func返回一个您想要等待的promise,如果没有return
,则在addPreset
解析之前,该过程仍在继续- 在几个函数中,您创建了一个deferred而不使用它-删除了
- 在您创建的其他地方,您解决并返回一个延迟,只需返回一个
q.resolve()
下面的代码根本不使用q
承诺,我已经改为原生Promise
来测试我的答案,但转换回q
应该很简单
function createNewPreset(){
return Promise.resolve({
"name" : undefined,
"unit" : undefined,
"interval" : undefined,
"files" : [],
});
}
function addPreset(){
console.log("adding");
return createNewPreset()
.then(function(){
console.log("Gettind input in addPreset");
})
.then(getUserInput)
.then(function(data){
console.log("Adding data " + data);
});
}
function getUserInput(){
return new Promise(function(resolve, reject) {
var stdin = process.stdin;
stdin.resume();
stdin.once('data', function(data){
data = data.toString().trim()
if(data.length > 20){
var err = new Error("The entered preset name is too long");
reject(err);
}
else{
resolve(data);
}
});
});
}
function processChoice(input){
return new Promise(function(resolve, reject) {
var error = undefined;
var func;
switch(input){
case "a":
func = addPreset;
break;
case "q":
func = function(){
process.exit();
}
break;
default:
error = new Error("Invalid menu option entered.");
reject(error);
break;
}
resolve(func);
});
}
function prompt(){
var stdout = process.stdout;
//indicates that prompt is being executed
stdout.write("(tic): ");
console.log("PROMPT waiting for input");
getUserInput()
.then(processChoice)
.then(function(func){ return func(); })
.catch(function(err) {console.log(err)})
.then(prompt);
}
prompt();