我正在做这样的事情
var command1;
var command2;
var fn = function(param) {
var deferred = Q.defer();
var command = spawn(..., [
... passing different arguments based on param ...
]);
...
command.stdout.on('data', function(data) {
if (/... if process started successfully .../.test(data)) {
deferred.resolve();
}
});
...
if (param === 'command1') {
command1 = command;
} else {
command2 = command;
}
return deferred.promise;
};
Q.all([
fn('command1'),
fn('command2')
]);
以后我打电话给command1.kill()
和command2.kill()
。我考虑过将command
传递给resolve
,但之后可能永远不会被调用。我也可以将command
传递给reject
,这样如果出现问题我就可以在kill
打电话,但这感觉很奇怪。
如何以惯用的方式向呼叫者返回command
和承诺?没有fn
中的条件部分。有什么可能性?
我还考虑过ES6的解构分配功能,但请考虑以下内容
...
return [command, deferred.promise];
}
[command1, promiseCommand1] = fn('command1');
[command2, promiseCommand2] = fn('command2');
Q.all([
promise1,
promise2.then(Q.all([
promiseCommand1,
promiseCommand2
])
]);
但是失败了(至少在我的特定情况下,命令应该等到promise2
被解决),因为当我通过promiseCommand1
和{{1}时,进程已经在路上了} promiseCommand2
。
不确定我是否使用了正确的解构赋值语法。
刚刚进入我的脑海
Q.all
还有其他方式吗?
从昨天开始,我已经想出如何使用解构赋值(仍然不确定语法)
var command1;
var command2;
var fn = function(param, callback) {
var deferred = Q.defer();
var command = spawn(..., [...]);
...
callback(command);
return deferred.promise;
};
Q.all([
fn('command1', function(command) {
command1 = command;
}),
fn('command1', function(command) {
command2 = command;
})
]);
这样命令只会在Q.all([
promise1,
promise2.then(function() {
[command1, promiseCommand1] = fn('command1');
[command2, promiseCommand2] = fn('command2');
return Q.all([
promiseCommand1,
promiseCommand2
]);
})
]);
解析后执行。
基于the accepted answer和我之前的更新,我想出了这个
promise2
工作,对我来说似乎是一个简洁的解决方案。我不想依赖ES6进行解构赋值。另外,我认为我不能使用该功能将一个值分配给在作用域外声明的变量,并简明地在本地作用域中指定另一个。返回
command.promise = deferred.promise;
return command;
};
Q.all([
promise1,
promise2.then(function() {
command1 = fn('command1');
command2 = fn('command2');
return Q.all([command1.promise, command2.promise]);
})
]);
也是一种可能的解决方案,但不够简洁。
return {
command: command,
promise: deferred.promise
};
在接受的答案的评论部分,我被建议在Q.all([
promise1,
promise2.then(function() {
var result1 = fn('command1');
var result2 = fn('command2');
command1 = result1.command;
command2 = result2.command;
return Q.all([result1.promise, result2.promise]);
})
]);
中致电reject
,以防止我的代码因未决承诺而永久挂起。我用以下
fn
使用 command.promise = deferred.promise.timeout(...);
return command;
};
将返回相同的承诺,但是如果未在给定的超时值中解析承诺,则承诺将自动被拒绝。
答案 0 :(得分:1)
您可以返回一个数组,然后使用promise.spread
方法。
https://github.com/kriskowal/q#combination
.then(function () {
return [command, promise];
})
.spread(function (command, promise) {
});
答案 1 :(得分:1)
你应该通过将“传递命令拒绝”放在头上来获得有用的东西。换句话说,拒绝响应kill()
命令。
正如您所知,问题是fn()
应该返回一个承诺,而承诺并不会自然地传达相应命令的.kill()
方法。但是,javascript允许将属性(包括函数(作为方法))动态附加到对象。因此,添加.kill()
方法很简单。
var fn = function(param) {
var deferred = Q.defer();
var command = spawn(..., [
... passing different arguments based on param ...
]);
...
command.stdout.on('data', function(data) {
if (/... if process started successfully .../.test(data)) {
deferred.resolve();
}
});
...
var promise = deferred.promise;
// Now monkey-patch the promise with a .kill() method that fronts for command.kill() AND rejects the Deferred.
promise.kill = function() {
command.kill();
deferred.reject(new Error('killed')); // for a more specific error message, augment 'killed' with something unique derived from `param`.
}
return promise;
};
var promise1 = fn('command1');
var promise2 = fn('command2');
Q.all([promise1, promise2]).spread(...).catch(...);
promise1.kill()
或promise2.kill()
会导致“已杀死”在捕获处理程序中显示为error.message
。
可以酌情调用两个杀戮,例如......
if(...) {
promise1.kill();
}
if(...) {
promise2.kill();
}
或者,.kill()
方法也可以干净地分离,而不需要.bind()
,例如:
doSomethingAsync(...).then(...).catch(promise1.kill);
doSomethingElseAsync(...).then(...).catch(promise2.kill);
请注意,fn()
适用于任意数量的来电,无需外部变量command1
,command2
等。