Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/node.js/33.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/288.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 如何同时从函数返回值和承诺?_Javascript_Node.js_Promise_Q - Fatal编程技术网

Javascript 如何同时从函数返回值和承诺?

Javascript 如何同时从函数返回值和承诺?,javascript,node.js,promise,q,Javascript,Node.js,Promise,Q,我在做这样的事情 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

我在做这样的事情

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()
。我曾想过将
命令
传递给
resolve
,但可能永远不会调用它。我还可以将
命令
传递给
拒绝
,这样如果出现问题,我就可以在那里调用
kill
,但这感觉很奇怪

如何以惯用的方式向调用者返回
命令
和承诺?在
fn
中没有条件部分。有什么可能性

我还考虑了ES6的解构赋值特性,但考虑下面的

  ...
  return [command, deferred.promise];
}

[command1, promiseCommand1] = fn('command1');
[command2, promiseCommand2] = fn('command2');

Q.all([
  promise1,
  promise2.then(Q.all([
    promiseCommand1,
    promiseCommand2    
  ])
]);
  command.promise = deferred.promise.timeout(...);
  return command;
};
但这失败了(至少在我的特殊情况下,命令应该等到
promise2
解决),因为当我将
promisecomand1
promisecomand2
传递到
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;
  })
]);
还有别的办法吗

更新 从昨天开始,我就知道如何使用解构赋值(仍然不确定语法)

这样,只有在解析了
promise2
之后,才会执行命令

解决方案 根据我之前的更新,我得出了这个结论

  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]);
  })
]);
对我来说,这是一个简洁的解决方案。我不想依赖ES6来完成解构任务。此外,我认为我不能使用该功能将一个值赋给在范围外声明的变量,而将另一个值赋给局部范围内的变量。返回

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]);
  })
]);
校正 在已接受答案的评论部分,我被建议在
fn
中调用
reject
,以防止我的代码因未决承诺而永久挂起。我用以下方法解决了这个问题

  ...
  return [command, deferred.promise];
}

[command1, promiseCommand1] = fn('command1');
[command2, promiseCommand2] = fn('command2');

Q.all([
  promise1,
  promise2.then(Q.all([
    promiseCommand1,
    promiseCommand2    
  ])
]);
  command.promise = deferred.promise.timeout(...);
  return command;
};

使用
timeout
将返回相同的承诺,但是如果承诺未在给定的超时值内解析,则承诺将自动被拒绝。

您可以返回一个数组,然后使用
promise.spread
方法


您可以返回一个数组,然后使用
promise.spread
方法


您应该通过将“passcommandtoreject”放在头上,从而得到一些有用的东西。换句话说,拒绝响应
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()
将导致“kill”在捕获处理程序中显示为
error.message

这两次杀戮可以适当地调用,例如

if(...) {
    promise1.kill();
}
if(...) {
    promise2.kill();
}
或者,
.kill()
方法也将干净地分离,而无需
.bind()
,例如:

doSomethingAsync(...).then(...).catch(promise1.kill);
doSomethingElseAsync(...).then(...).catch(promise2.kill);

请注意,
fn()
将适用于任何数量的调用,而不需要外部变量
command1
command2
等。

您应该通过在其头部旋转“pass command to reject”来获得有用的结果。换句话说,拒绝响应
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()
将导致“kill”在捕获处理程序中显示为
error.message

这两次杀戮可以适当地调用,例如

if(...) {
    promise1.kill();
}
if(...) {
    promise2.kill();
}
或者,
.kill()
方法也将干净地分离,而无需
.bind()
,例如:

doSomethingAsync(...).then(...).catch(promise1.kill);
doSomethingElseAsync(...).then(...).catch(promise2.kill);

请注意,
fn()
将适用于任何数量的调用,而不需要外部变量
command1
command2
等。

promise2的问题。然后(Q.all([是
的参数。然后
必须是函数)-否则,它们是有效的ignored@JaromandaX是的,我的例子是错的。但是它是有教育意义的:)promise2的问题。然后(Q.all([是
的参数)。然后
必须是函数-否则它们是有效的ignored@JaromandaX是的,我的例子是错的。但它是有教育意义的:)如果我从
fn
返回
[command,deferred.promise];
那么函数将不会返回承诺,而是返回第二个元素是承诺的数组。要使用
spread
我必须解析为数组,否?
deferred.resolve([…])
那么我是否可以使用
spread
。无论如何,我不明白你的意思。对不起。你能详细说明一下吗?如果我返回
[命令,延迟。承诺];
from
fn
则函数将不会返回承诺,而是返回第二个元素为承诺的数组。要使用
spread
我必须解析为数组,否?
延迟。解析([…])
那么我可以使用
spread
。无论如何,我不明白你的意思。对不起。你能详细说明一下吗?很好的想法,但是我认为我做不到。我在问题中没有提到它(虽然没关系,但事实上确实如此),但我在量角器集成测试的
启动前
函数中启动命令,并在
启动后
中调用
kill
。我从
启动前
返回,并承诺延迟启动测试,直到我的进程启动