2015-10-08 11 views
3

Хотя кодирование в node.js (которое является асинхронным), могу ли я полагаться на мои закодированные команды, которые должны выполняться по порядку?Прикованные команды всегда выполняются в порядке?

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

Будет start запустить первый, а затем doAThing, а затем stop?

+1

Да, они всегда будут выполняться по порядку. – idbehold

+1

Краткий ответ: ** Да ** –

+1

Сами функции будут выполняться в ожидаемом порядке, однако действия, указанные в функции, могут не выполняться в ожидаемом порядке. –

ответ

1

tl; dr Технически, да, но вы можете рассмотреть возможность организации кода по-другому, если некоторые функции в цепочке асинхронны.


Например, каждый метод в последовательности x.start().doAThing().stop() является вызовом метода, и это требует какого-либо объекта, чтобы работать на. Для того, чтобы позвонить в doAThing(), виртуальная машина JavaScript должна сначала оценить 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

Это зависит от того, что делают эти функции. Если вы не используете обратный вызов, команды выполняются по порядку. Однако, если для логики вашей функции start() требуется асинхронный вызов, результат будет доступен только после завершения вызова. Это означает, что последующая функция doAThing() не может использовать результаты асинхронного вызова внутри вашей функции start().

+0

Обратный вызов не изменит порядок выполнения. Это IO vs вычисления, которые изменят порядок выполнения. –

+0

Да. Как правило, команды ввода-вывода используют обратные вызовы для возврата результата. Но функции типа Array.prototype.map() или Array.prototype.forEach() используют обратный вызов синхронно. Спасибо за исправление. –

1

Технически, ответ всегда да. В то время как x.start() с огнем сразу же, если он выполняет операцию io, время выполнения узла будет создавать поток для выполнения этой операции, следовательно, асинхронный запуск сразу же запускается, а x.start().doAThing() будет срабатывать при возврате x.start(). Однако asynch io может вернуться с ответом после возвращения функции, поэтому, если это асинхронный, .doAThing() не получит ответа. Вот почему асинхронные функции используют функции callbacks/promises/ES7 asynch, а также могут быть использованы технически генераторы ES6, которые могут получить доступ к отклику io. Пока это не операция io, Nodejs является синхронным.

Так

function start(){ 
    var a = 1 + 1; 
    return { 
     doAthing: function(){ return a;} 
    }; 
} 

Будет полностью synchronus.

Смежные вопросы