code: public static <T> ChannelSupplier<T> concat(Iterator<? extends ChannelSupplier<? extends T>> iterator) {
  		return new AbstractChannelSupplier<T>() {
  			ChannelSupplier<? extends T> current = ChannelSupplier.of();
  
  			@Override
  			protected Promise<T> doGet() {
  				return current.get()
  						.thenEx((value, e) -> {
  							if (e == null) {
  								if (value != null) {
  									return Promise.of(value);
  								} else {
  									if (iterator.hasNext()) {
  										current = iterator.next();
  										return get();
  									} else {
  										return Promise.of(null);
  									}
  								}
  							} else {
  								while (iterator.hasNext()) {
  									iterator.next().close(e);
  								}
  								return Promise.ofException(e);
  							}
  						});
  			}
  
  			@Override
  			protected void onClosed(@NotNull Throwable e) {
  				current.close(e);
  				while (iterator.hasNext()) {
  					iterator.next().close(e);
  				}
  			}
  		};
  	}
docs: Creates a new ChannelSupplier which on {@code get()} call returns
  the result wrapped in {@code promise} of the first ChannelSuppliers'
  {@code promise} that was successfully completed with a non-null result.
  If all of the ChannelSuppliers of the iterator have a {@code null}
  {@code promise} result, a {@code promise} of {@code null} will be returned.
  <p>
  If one of the ChannelSuppliers' {@code promises} completes with an exception,
  all subsequent elements of the iterator will be closed and a
  {@code promise} of exception will be returned.
  
  @param iterator an iterator of ChannelSuppliers
  @param <T>      type of data wrapped in the ChannelSuppliers
  @return a ChannelSupplier of {@code <T>}