Node.js ES5,如何在循环中使用承诺

Node.js ES5,如何在循环中使用承诺,node.js,loops,promise,Node.js,Loops,Promise,假设命令长度=2 当我运行下面的函数device_execute_命令时。执行消息顺序为 finish one command finish one command has latest state? has latest state? 我预计: finish one command has latest state? finish one command has latest state? 代码 var设备执行命令=功能(命令arr){ //这是主回路 var i=0; 对于(i=0;i

假设命令长度=2

当我运行下面的函数device_execute_命令时。执行消息顺序为

finish one command
finish one command
has latest state?
has latest state?
我预计:

finish one command
has latest state?
finish one command
has latest state?
代码

var设备执行命令=功能(命令arr){
//这是主回路
var i=0;
对于(i=0;i
这是由于javascript的异步特性造成的。你想要的是一个接一个地履行承诺。这不能通过简单地在循环迭代中调用承诺来实现。实现这一点最简单的方法可能是使用
bluebird
promise实现,它附带了许多用于承诺执行流控制的方法

例如,您的案例中的顺序执行可以通过以下方式实现:

const Promise = require('bluebird');

Promise.each(command_arr, function(command) {
  return device_run_single_command(command).then(function(command) {
    console.log();
    console.log("finish one command");
    console.log(command);    
    return is_device_has_latest_state(command);
  }).then(function(command_with_condi) {
    console.log();
    console.log("has latest state?");
    console.log(command_with_condi);    
  });
});

问题在于承诺是异步的,而SimpleFor循环不会暂停下一次迭代以等待上一次迭代完成

相反,您应该重新设计您的循环逻辑,并且只在上一次迭代完成后运行下一次迭代。例如,对于iLife,您可以这样做:

var device_execute_command = function(command_arr) {

  var i = 0;

  (function next() {
    command_arr[i] && device_run_single_command(command_arr[i++]).then(function(command) {
        console.log();
        console.log("finish one command");
        console.log(command);
        return is_device_has_latest_state(command);
      })
      .then(function(command_with_condi) {
        console.log();
        console.log("has latest state?");
        console.log(command_with_condi);
      })
      .then(next);
  })();

}

如前所述,JavaScript承诺本质上是异步的。因此,在调用“device\u run\u single\u command(command)”函数之后,for循环将移动到下一个迭代。因此,可以观察到输出

在JavaScript中,这个问题可以通过各种机制来解决。Yerken和dfsq建议的方法肯定会奏效。随着async/await将来的到来,您甚至可以通过保持原来的for循环结构来解决这个问题。目前,可以使用babel编译器使用async/await

async function device_execute_command(command_arr) {
  // This is the main loop
  var i = 0;
  for(i=0; i < command_arr.length; i++) {
    var command = command_arr[i];
    var command_id = command.command_id;

    command = await device_run_single_command(command);
    console.log();
    console.log("finish one command");
    console.log(command);

    var command_with_condi = await is_device_has_latest_state(command);
    console.log();
    console.log("has latest state?");
    console.log(command_with_condi);

  }

}
异步功能设备执行命令(命令arr){
//这是主回路
var i=0;
对于(i=0;i
async function device_execute_command(command_arr) {
  // This is the main loop
  var i = 0;
  for(i=0; i < command_arr.length; i++) {
    var command = command_arr[i];
    var command_id = command.command_id;

    command = await device_run_single_command(command);
    console.log();
    console.log("finish one command");
    console.log(command);

    var command_with_condi = await is_device_has_latest_state(command);
    console.log();
    console.log("has latest state?");
    console.log(command_with_condi);

  }

}