Как указано в документации React, нет гарантии того, что setState
запущен синхронно, поэтому ваш console.log
может вернуть состояние до его обновления.
Майкл Паркер упоминает о передаче обратного вызова внутри setState
. Другой способ обработки логики после изменения состояния осуществляется с помощью метода жизненного цикла componentDidUpdate
, который является методом, рекомендованным в документах React.
Обычно мы рекомендуем использовать для этой логики componentDidUpdate ().
blockquote>Это особенно полезно, когда могут быть последовательные
setState
s, и вы хотели бы запустить ту же функцию после каждого изменения состояния. Вместо добавления обратного вызова к каждомуsetState
, вы можете поместить функцию внутриcomponentDidUpdate
с конкретной логикой внутри, если необходимо.// example componentDidUpdate(prevProps, prevState) { if (this.state.value > prevState.value) { this.foo(); } }
Вместо того, чтобы требовать тип кортежа (пары), почему бы просто не принять селектор:
public static IEnumerable<TResult> Pairwise<TSource, TResult>(this IEnumerable<TSource> source, Func<TSource, TSource, TResult> resultSelector)
{
TSource previous = default(TSource);
using (var it = source.GetEnumerator())
{
if (it.MoveNext())
previous = it.Current;
while (it.MoveNext())
yield return resultSelector(previous, previous = it.Current);
}
}
Что позволяет вам пропустить промежуточный объект, если вы хотите:
string[] items = new string[] { "a", "b", "c", "d" };
var pairs = items.Pairwise((x, y) => string.Format("{0},{1}", x, y));
foreach(var pair in pairs)
Console.WriteLine(pair);
Или вы можете использовать анонимный тип:
var pairs = items.Pairwise((x, y) => new { First = x, Second = y });
Существует несколько решений (ни одно из них не является идеальным)
Они уже его поддерживают. Это открытый исходный код, но у них есть какая-то двойная лицензия , поэтому лучше проверить, можно ли использовать для вашего проекта.
APE - это структура комет, но они недавно начали поддерживать Websockets. На их веб-сайте (раздел «APE как прокси») они говорят, что он может запускать js.io библиотеки, которые включают xmpp.js, поэтому их объединение может работать.
Это рамка на основе Java, похожая на APE, которая обеспечивает одну остановку в магазине Comet решения, и они, похоже, поддерживают как XMPP и WebSockets
Strophe выполняет XMPP через BOSH (двунаправленные потоки через синхронный HTTP), но существует также обсуждение поддержки WebSockets .
Джек Моффитт (основной разработчик и автор упомянутой выше книги), похоже, заинтересован в WebSockets, но нам нужно дать более убедительные рассуждения о том, почему они должны поддерживать WebSocket по BOSH. Если у вас есть хорошие ответы, пожалуйста, присоединяйтесь к протектору.
Я только что попробовал их пример xmpp, bosh, strophe echobot , который хорошо сработал. Вы также можете попробовать его, чтобы посмотреть, соответствует ли он вашим требованиям или нет.
Для # 2 и # 3, они говорят, что они оба поддерживают xmpp и веб-сайты, но не уверены, если они работают вместе.
Для какого приложения вы думаете об использовании XMPP и WebSockets?
Ниже приводятся предложения по альтернативным вариантам.
Я получил большую часть информации выше, когда написал этот блог . Если вы проверите раздел комментариев время от времени, я опубликую обновление, как только найду другие решения.
-121--1305516-Я никогда не был в восторге от этого решения. Для одного, это не обязательно очевидно, где все такие методы в коде, для другого, я просто не люблю синтаксис. Я хочу использовать. когда я вызываю методы!
И я хочу использовать $! --- &
при вызове методов! Разберись. Если вы собираетесь написать код C++, придерживайтесь условных обозначений C++. И очень важным соглашением C++ является предпочтение функций, не являющихся членами, когда это возможно.
Существует причина, по которой гуру C++ рекомендуют это:
Это улучшает инкапсуляцию, расширяемость и повторное использование. ( std::сортировка
может работать со всеми парами итераторов , поскольку не является членом ни одного класса итераторов или контейнеров. И как бы вы ни расширяли std:: Последовательностью
, вы не можете ломать его, пока придерживаетесь не-членских функций. И даже если у вас нет доступа к исходному коду класса или нет разрешения на его изменение, вы все равно можете расширить его, определив функции, не являющиеся членами класса)
Лично я не вижу точки в вашем коде. Разве это не намного проще, удобнее для чтения и короче?
string OperateOnString( float num, string a, string b )
{
string nameS;
Format(nameS, "%f-%s-%s", num, a.c_str(), b.c_str() );
return nameS;
}
// or even better, if `Format` is made to return the string it creates, instead of taking it as a parameter
string OperateOnString( float num, string a, string b )
{
return Format("%f-%s-%s", num, a.c_str(), b.c_str() );
}
Когда в Риме, делайте как римляне, как говорится. Особенно , когда у римлян есть веские причины поступать так, как у них есть. И особенно когда ваш собственный способ сделать это на самом деле не имеет ни одного преимущества. Он более подвержен ошибкам, сбивает с толку людей, читающих ваш код, не является идиоматическим, и это просто больше строк кода, чтобы сделать то же самое.
Что касается вашей проблемы, трудно найти функции, не являющиеся членами, которые расширяют последовательности
, поместите их в пространство имен, если это связано. Для этого они и нужны. Создайте пространство имен StringUtil
или что-то подобное и поместите их туда.
Модуль F # Seq
определяет парную функцию над IEnumerable < T >
, но эта функция отсутствует в рамку .NET.
Если бы он уже был в .Рамка, вместо возврата пар он, вероятно, принял бы функцию селектора из-за отсутствия поддержки кортежей на языках, таких как C # и VB.
var pairs = ns.Pairwise( (a, b) => new { First = a, Second = b };
Я не думаю, что какие-либо из ответов здесь действительно улучшить на ваш простой итератор реализации, которая казалась наиболее естественным для меня (и плакат dahlbyk по взглядам вещей!) тоже.
Примерно так:
public static IEnumerable<TResult> Pairwise<T, TResult>(this IEnumerable<T> enumerable, Func<T, T, TResult> selector)
{
var previous = enumerable.First();
foreach (var item in enumerable.Skip(1))
{
yield return selector(previous, item);
previous = item;
}
}
В .NET 4 это становится еще проще: -
var input = new[] { "a", "b", "c", "d", "e", "f" };
var result = input.Zip(input.Skip(1), (a, b) => Tuple.Create(a, b));
Подробно останавливание предыдущий ответ для предотвращения O (n <глоток> 2 глоток>) приближается путем явного использования переданного итератора:
public static IEnumerable<IEnumerable<T>> Tuples<T>(this IEnumerable<T> input, int groupCount) {
if (null == input) throw new ArgumentException("input");
if (groupCount < 1) throw new ArgumentException("groupCount");
var e = input.GetEnumerator();
bool done = false;
while (!done) {
var l = new List<T>();
for (var n = 0; n < groupCount; ++n) {
if (!e.MoveNext()) {
if (n != 0) {
yield return l;
}
yield break;
}
l.Add(e.Current);
}
yield return l;
}
}
Для C# 2, перед дополнительными методами, отбрасывают "это" от входного параметра и вызова как статический метод.
Решение C# 3.0 (извините:)
public static IEnumerable<IEnumerable<T>> Tuples<T>(this IEnumerable<T> sequence, int nTuple)
{
if(nTuple <= 0) throw new ArgumentOutOfRangeException("nTuple");
for(int i = 0; i <= sequence.Count() - nTuple; i++)
yield return sequence.Skip(i).Take(nTuple);
}
Это не является самым производительным в мире, но это уверено приятный посмотреть на.
Действительно, единственная вещь, делающая это, решением C# 3.0 является.Skip. Возьмите конструкцию, поэтому если Вы просто изменяете это на добавление элементов в том диапазоне к списку вместо этого, это должно быть золотым для 2,0. Тем не менее это все еще не производительно.
Альтернатива Pairs
реализация, с помощью последней пары, которая сохранит предыдущее значение:
static IEnumerable<Pair<T, T>> Pairs( IEnumerable<T> collection ) {
Pair<T, T> pair = null;
foreach( T item in collection ) {
if( pair == null )
pair = Pair.Create( default( T ), item );
else
yield return pair = Pair.Create( pair.Second, item );
}
}
Простой Window
реализация (только безопасный для личного пользования, если вызывающая сторона не сохраняет возвращенные массивы; см. примечание):
static IEnumerable<T[]> Window( IEnumerable<T> collection, int windowSize ) {
if( windowSize < 1 )
yield break;
int index = 0;
T[] window = new T[windowSize];
foreach( var item in collection ) {
bool initializing = index < windowSize;
// Shift initialized window to accomodate new item.
if( !initializing )
Array.Copy( window, 1, window, 0, windowSize - 1 );
// Add current item to window.
int itemIndex = initializing ? index : windowSize - 1;
window[itemIndex] = item;
index++;
bool initialized = index >= windowSize;
if( initialized )
//NOTE: For public API, should return array copy to prevent
// modifcation by user, or use a different type for the window.
yield return window;
}
}
использование В качестве примера:
for( int i = 0; i <= items.Length; ++i ) {
Console.WriteLine( "Window size {0}:", i );
foreach( string[] window in IterTools<string>.Window( items, i ) )
Console.WriteLine( string.Join( ", ", window ) );
Console.WriteLine( );
}