链式命令总是按顺序执行吗?

时间:2015-10-08 16:57:03

标签: javascript node.js asynchronous

在node.js中编码(这是异步的)时,我可以依赖我的链式命令按顺序执行吗?

var x=new MyObject();
x.start().doAThing().stop()

首先start先运行,然后doAThing然后stop

3 个答案:

答案 0 :(得分:2)

这取决于这些功能正在做什么。除非您使用回调,否则命令将按顺序执行。但是,如果start()函数的逻辑需要异步调用,则只有在调用完成后结果才可用。这意味着后续的doAThing()函数不能在start()函数中使用异步调用的结果。

答案 1 :(得分:1)

tl; dr 从技术上讲,是的,但如果链中的某些函数是异步的,您可能需要考虑以不同的方式组织代码。

例如,序列x.start().doAThing().stop()中的每个方法都是一个方法调用,它需要一些对象来操作。要调用doAThing(),JavaScript VM必须首先评估x.start(),然后查找doAThing函数,然后才能开始执行doAThing的正文

根据doAThing的值,x.start()做什么可​​能完全不同!

MyObject.prototype.start = function () {
  if (/* condition */) {
    return {
      doAThing: function () {
        return {
          stop: function () {
            console.log('path1');
          }
        };
      }
    };
  }
  else {
    return {
      doAThing: function () {
        return {
          stop: function () {
            console.log('path2');
          }
        };
      }
    };
  }
};

但是,您的函数可以启动可能无序发生的异步任务。

MyObject.prototype.start = function () {
  setTimeout(function () {
    // This will happen out-of-order, usually after `stop` returns!
    console.log('timed out');
  }, 0);

  return {
    doAThing: function () {
      return {
        stop: function () {
          console.log('stop');
        }
      };
    }
  };
};

jsbin。输出:

stop
timed out

如果必须链接异步函数,则必须使用回调,承诺或生成器重写代码。例如,使用承诺:

var start = function (obj) {
  return new Promise(function (resolve) {
    setTimeout(function () {
      // This will happen in order.                                            
      console.log('timed out');
      resolve(obj);
    }, 0);
  });
};

var doAThing = function (obj) {
  return Promise.resolve(obj);
};

var stop = function (obj) {
  // Synchronous functions are fine, too.                                      
  console.log('stop');
};

此链将按顺序执行这些功能:

Promise.resolve(x)
  .then(start)
  .then(doAThing)
  .then(stop);

输出:

timed out
stop

答案 2 :(得分:1)

从技术上讲,答案总是肯定的。当exit立即着火时,如果它执行io操作,Node的运行时将创建一个线程来执行该操作,因此异步,start仍然立即被触发,x.start()将在x.start().doAThing()返回时开火。但是,asynch io可以在函数返回后返回响应,因此如果它是异步的,x.start()不会有响应。这就是asynch函数使用回调/ promises / ES7异步函数的原因,技术上也可以使用ES6生成器,它可以访问io响应。只要它不是io操作,Nodejs就是同步。

所以

.doAThing()

将完全同步。