2016-07-06 3 views
3

Я работаю с JavaScript обещает в последнее время и наткнулся на следующую ситуацию, которая заставила меня задуматься:Выполняют ли обещания асинхронно или синхронно?

var combinedArray = []; 

function getArrayOne() { 
    $http.post(arrayOnePath).then(function(arr) { 
     combinedArray = combinedArray.concat(arr); 
    }) // More code preventing me from using Promise.all(...) 
} 

function getArrayTwo() { 
    $http.post(arrayTwoPath).then(function(arr) { 
     combinedArray = combinedArray.concat(arr); 
    }) // More code preventing me from using Promise.all(...)  
} 

function getAllArrays() { 
    getArrayOne(); 
    getArrayTwo(); 
} 

Пока я писал эту логику до меня дошло, что может быть потенциальным условия гонки, если оба обещания решить в то же время (когда они обращаются к общему ресурсу). Подумав об этом еще некоторое время, я понял, что после сообщения post выполняются разрешения then(..), что означает, что этот код работает в среде синхронного выполнения JavaScript.

Может ли кто-то предоставить мне некоторую ясность в отношении того, могут ли два заявления combinedArray.concat(arr); вызвать проблему, если обе обетования будут разрешены одновременно?

[Редактировать] Следуя некоторым комментариям, я просто хочу добавить, что я не против, какой порядок объединяет массивы в combinedArray.

+1

До тех пор, пока ваша логика не зависит от того, какой заказ отправляет решение, вы в порядке. Вы столкнулись бы только с проблемой, если, например, mixedArray [0] всегда должен быть первой записью из getArrayOne. – Shilly

+2

Состояние гонки, если вы ожидаете, что ваш 'объединенныйArray' будет иметь заданный порядок. Но нет, два обратных вызова javascript никогда не вызываются одновременно. – Bergi

+0

Несмотря на то, что ответ «один поток» Javascript - это тот, который вы искали, другое чтение названия вопроса напоминает [этот вопрос SO] (http://stackoverflow.com/q/38059284/1426891) («Почему JavaScript Promise, а затем обработчик запускается после другого кода? »), Спрашивая, как обработчики' then' гарантированно будут вызываться асинхронно. –

ответ

3

JavaScript является однопоточным, предотвращая условия гонки даже при выполнении асинхронных вызовов.

Есть случаи, когда JS будет использовать другой поток в фоновом режиме, например, функции ввода-вывода узла, а API-интерфейс веб-рабочих позволяет вам создавать изолированный, но отдельный поток (без доступа к памяти, но они могут передавать сообщения).

Поскольку JS изначально был однопоточным, и все, что в нем зависит, зависит от этого (и использует старый код), они не могут просто добавить многопоточность и потенциальные условия гонки. Это сломает все. Таким образом, этот код всегда будет работать корректно и безопасно, поскольку обещания будут добавляться в одну очередь и разрешать друг за другом.

Даже в веб-работниках (и эквиваленте узлов) каждый «поток» имеет изолированное пространство памяти и не может напрямую обращаться к переменным из другого потока. Веб-работники специально используют postMessage method для сериализации объектов и безопасного отправления их в другой поток.

+0

Итак, я могу столкнуться с проблемами с 'объединенным массивом', если оба решения одновременно? [Ответил в редакции] –

+2

@NicholasRobinson No –

+0

@NicholasRobinson, [вы захотите узнать о цикле событий] (http://stackoverflow.com/q/21607692/497418). – zzzzBov

1

Что следует знать о функциях, передаваемых в API Promise:

  • Функе fn, который передается к исполнителю Promise (new Promise(fn)) выполняется немедленно.

  • Функция fn, которая передается обработчику (.then(fn)), выполняется асинхронно.

Никакие две функции никогда не будет выполняться в одно и то же время в среде JavaScript, если вы не используете Web Workers (спасибо @zzzzBov). В любом случае, это не то, что означает или подразумевает асинхронность.

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


"Race condition" Wikipedia:

Состояние гонки или расы опасности является поведение электронного, программного обеспечения или другой системы, где выходной сигнал зависит от последовательности или времени других неконтролируемых событий. Это становится ошибкой, когда события не происходят в том порядке, в котором программист намеревался.

+1

«Две функции никогда не будут выполняться одновременно в среде JavaScript». Знаете ли вы, что веб-работники предоставляют многопоточные возможности? – zzzzBov

+0

@zzzzBov Добавил, что предостережение от моего ответа. Спасибо. :-) – sdgluck

+2

@zzzzBov: Можно утверждать, что каждый рабочий работает в своей собственной среде. – Bergi

0

Как я уже объяснял, ваш Javascript на уровне пользователя является однопоточным (за исключением webWorkers, которые здесь не задействованы).

Никакие две части вашего Javascript не работают в тот же самый момент, так что у вас нет состояния гонки. В вашем конкретном примере кода есть проблема, зная, когда выполняются обе операции async, чтобы вы могли использовать результаты. Таким образом, вы можете использовать конструкцию вроде этого:

function getArrayOne() { 
    return $http.post(arrayOnePath).then(function(arr) { 
     // do any processing here on or with arr 
     return arr; 
    }) 
} 

function getArrayTwo() { 
    return $http.post(arrayTwoPath).then(function(arr) { 
     // do any processing here on or with arr 
     return arr; 
    }) 
} 

function getAllArrays() { 
    return Promise.all(getArrayOne(), getArrayTwo()).then(function(results) { 
     // results[0] is first array 
     // results[1] is second array 
     return results[0].concat(results[1]); 
    }); 
} 

getAllArrays().then(function(results) { 
    // all results available 
}, function(err) { 
    // error occurred here in either async operation 
}); 

Это не только сказать вам, когда все операции асинхронных сделаны и дать вам объединенные результаты, но они в порядке, и он распространяется ошибки или от работы ,

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