问:
Azure File Rest API Create Directory Fails Authentication but List Directory works
So i am having an issue with the Azure Rest API for creating directories and files. I can list directories and files, which uses the same method to create the Authorization header, but i always get the 403 - Server failed to authenticate the request. The first block of code below is the code to obtain a list of directories which works.

```<code>String uri = string.Format($"https://{_azureClientSettings.StorageAccountName}.file.core.windows.net/{_azureClientSettings.StorageShare}?restype=directory&comp=list");

                // Set this to whatever payload you desire. Mine is null because i'm not passing anything in.
                Byte[] requestPayload = null;

                //Instantiate the request message with a null payload.
                using (var httpRequestMessage = new HttpRequestMessage(HttpMethod.Get, uri)
                { Content = (requestPayload == null) ? null : new ByteArrayContent(requestPayload) })
                {

                    // Add the request headers for x-ms-date and x-ms-version.
                    DateTime now = DateTime.UtcNow;
                    httpRequestMessage.Headers.Add("x-ms-date", now.ToString("R", CultureInfo.InvariantCulture));
                    httpRequestMessage.Headers.Add("x-ms-version", "2017-04-17");

                    // Add the authorization header.
                    httpRequestMessage.Headers.Authorization = AzureStorageAuthenticationHelper.GetAuthorizationHeader(
                       _azureClientSettings.StorageAccountName, _azureClientSettings.StorageAccountKey, now, httpRequestMessage);

                    // Send the request.
                    using (HttpResponseMessage httpResponseMessage = await _httpClientRepo.Instance().SendAsync(httpRequestMessage, CancellationToken.None))
                    {
                        if (httpResponseMessage.StatusCode == HttpStatusCode.OK)
                        {
                            ...
                        }
                    }
                }
            }
</code>```

This block of code is the code i use in an attempt to create a directory, which fails.

```<code>Uri storageUri = new Uri($"https://{_azureClientSettings.StorageAccountName}.file.core.windows.net/{_azureClientSettings.StorageShare}/{directoryName}?restype=directory");

using (var httpRequestMessage = new HttpRequestMessage(HttpMethod.Put, storageUri)
{ Content = new StringContent("") })
{
                var now = DateTime.UtcNow;
                httpRequestMessage.Headers.Add("x-ms-date", now.ToString("R", CultureInfo.InvariantCulture));
                httpRequestMessage.Headers.Add("x-ms-version", "2017-04-17");
                httpRequestMessage.Headers.Add("x-ms-content-length", "200");
                httpRequestMessage.Headers.Add("x-ms-type", "file");

                // Add the authorization header.
                httpRequestMessage.Headers.Authorization = AzureStorageAuthenticationHelper.GetAuthorizationHeader(
                    _azureClientSettings.StorageAccountName, _azureClientSettings.StorageAccountKey, now, httpRequestMessage);

                // Send the request.
                using (var httpResponseMessage = await _httpClientRepo.Instance().SendAsync(httpRequestMessage, CancellationToken.None))
            {
               ...
            }
}
</code>```

As i say, i have a very similar method for creating a file and that also fails with a 403.I have taken the authorization header creation from https://github.com/mstaples84/azurefileserviceauth/blob/4bce5c268cd9ce6c91d9e8723ce72eb5e0df3255/SimpleAzureFileServiceDemo/AzureStorageAuthenticationHelper.cs

Any help would be much appreciated.

答:
As discussed in the comments, there was an issue with the code in AzureStorageAuthenticationHelper.

Here's the code I wrote that worked:

```<code>using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;
using Azure.Storage.Blobs;
using System.Net.Http;
using System.Globalization;
using System.Net.Http.Headers;
using System.Collections.Specialized;
using System.Web;
using System.Security.Cryptography;

namespace ConsoleApp1
{
    class Program
    {
        const string accountName = "myaccountname";
        const string accountKey = "myaccountkey";
        const string shareName = "test";
        const string directory = "test";

        static void Main(string[] args)
        {
            Uri storageUri = new Uri($"https://{accountName}.file.core.windows.net/{shareName}/{directory}?restype=directory");

            using (var httpRequestMessage = new HttpRequestMessage(HttpMethod.Put, storageUri)
            { Content = new StringContent("") })
            {
                var now = DateTime.UtcNow;
                httpRequestMessage.Headers.Add("x-ms-date", now.ToString("R", CultureInfo.InvariantCulture));
                httpRequestMessage.Headers.Add("x-ms-version", "2017-04-17");
                httpRequestMessage.Headers.Add("x-ms-content-length", "200");
                httpRequestMessage.Headers.Add("x-ms-type", "file");

                // Add the authorization header.
                httpRequestMessage.Headers.Authorization = AzureStorageAuthenticationHelper.GetAuthorizationHeader(
                    accountName, accountKey, now, httpRequestMessage);

                // Send the request.
                using (var response = new HttpClient().SendAsync(httpRequestMessage).GetAwaiter().GetResult())
                {
                    Console.WriteLine("Directory created successfully.");
                }
            }

        }
    }

    internal static class AzureStorageAuthenticationHelper
    {
        /// <summary>
        /// This creates the authorization header. This is required, and must be built
        ///   exactly following the instructions. This will return the authorization header
        ///   for most storage service calls.
        /// Create a string of the message signature and then encrypt it.
        /// </summary>
        /// <param name="storageAccountName">The name of the storage account to use.</param>
        /// <param name="storageAccountKey">The access key for the storage account to be used.</param>
        /// <param name="now">Date/Time stamp for now.</param>
        /// <param name="httpRequestMessage">The HttpWebRequest that needs an auth header.</param>
        /// <param name="ifMatch">Provide an eTag, and it will only make changes
        /// to a blob if the current eTag matches, to ensure you don't overwrite someone else's changes.</param>
        /// <param name="md5">Provide the md5 and it will check and make sure it matches the blob's md5.
        /// If it doesn't match, it won't return a value.</param>
        /// <returns></returns>
        internal static AuthenticationHeaderValue GetAuthorizationHeader(
           string storageAccountName, string storageAccountKey, DateTime now,
           HttpRequestMessage httpRequestMessage, string ifMatch = "", string md5 = "")
        {
            // This is the raw representation of the message signature.
            var method = httpRequestMessage.Method;

            // content length
            var contentLength = string.Empty;
            if (!(method == HttpMethod.Get || method == HttpMethod.Head))
            {
                var length = httpRequestMessage.Content?.Headers.ContentLength;

                if (length != null && length > 0)
                {
                    contentLength = length.ToString();
                }
            }

            String messageSignature = String.Format("{0}\n\n\n{1}\n{5}\n{7}\n{6}\n\n{2}\n\n\n\n{3}{4}",
                      method.ToString().ToUpper(),
                      contentLength,
                      ifMatch,
                      GetCanonicalizedHeaders(httpRequestMessage),
                      GetCanonicalizedResource(httpRequestMessage.RequestUri, storageAccountName),
                      md5,
                      string.Empty,
                      httpRequestMessage.Content?.Headers.ContentType.ToString() ?? string.Empty);

            // Now turn it into a byte array.
            var signatureBytes = Encoding.UTF8.GetBytes(messageSignature);

            // Create the HMACSHA256 version of the storage key.
            var SHA256 = new HMACSHA256(Convert.FromBase64String(storageAccountKey));

            // Compute the hash of the SignatureBytes and convert it to a base64 string.
            var signature = Convert.ToBase64String(SHA256.ComputeHash(signatureBytes));

            // This is the actual header that will be added to the list of request headers.
            // You can stop the code here and look at the value of 'authHV' before it is returned.
            var authHV = new AuthenticationHeaderValue("SharedKey",
                storageAccountName + ":" + signature);
            return authHV;
        }

        /// <summary>
        /// Put the headers that start with x-ms in a list and sort them.
        /// Then format them into a string of [key:value\n] values concatenated into one string.
        /// (Canonicalized Headers = headers where the format is standardized).
        /// </summary>
        /// <param name="httpRequestMessage">The request that will be made to the storage service.</param>
        /// <returns>Error message; blank if okay.</returns>
        private static string GetCanonicalizedHeaders(HttpRequestMessage httpRequestMessage)
        {
            var headers = from kvp in httpRequestMessage.Headers
                          where kvp.Key.StartsWith("x-ms-", StringComparison.OrdinalIgnoreCase)
                          orderby kvp.Key
                          select new { Key = kvp.Key.ToLowerInvariant(), kvp.Value };

            StringBuilder sb = new StringBuilder();

            // Create the string in the right format; this is what makes the headers "canonicalized" --
            //   it means put in a standard format. http://en.wikipedia.org/wiki/Canonicalization
            foreach (var kvp in headers)
            {
                StringBuilder headerBuilder = new StringBuilder(kvp.Key);
                char separator = ':';

                // Get the value for each header, strip out \r\n if found, then append it with the key.
                foreach (string headerValues in kvp.Value)
                {
                    string trimmedValue = headerValues.TrimStart().Replace("\r\n", String.Empty);
                    headerBuilder.Append(separator).Append(trimmedValue);

                    // Set this to a comma; this will only be used
                    //   if there are multiple values for one of the headers.
                    separator = ',';
                }
                sb.Append(headerBuilder.ToString()).Append("\n");
            }
            return sb.ToString();
        }

        /// <summary>
        /// This part of the signature string represents the storage account
        ///   targeted by the request. Will also include any additional query parameters/values.
        /// For ListContainers, this will return something like this:
        ///   /storageaccountname/\ncomp:list
        /// </summary>
        /// <param name="address">The URI of the storage service.</param>
        /// <param name="accountName">The storage account name.</param>
        /// <returns>String representing the canonicalized resource.</returns>
        private static string GetCanonicalizedResource(Uri address, string storageAccountName)
        {
            // The absolute path is "/" because for we're getting a list of containers.
            StringBuilder sb = new StringBuilder("/").Append(storageAccountName).Append(address.AbsolutePath);

            // Address.Query is the resource, such as "?comp=list".
            // This ends up with a NameValueCollection with 1 entry having key=comp, value=list.
            // It will have more entries if you have more query parameters.
            NameValueCollection values = HttpUtility.ParseQueryString(address.Query);

            foreach (var item in values.AllKeys.OrderBy(k => k))
            {
                sb.Append('\n').Append(item).Append(':').Append(values[item]);
            }

            return sb.ToString();

        }
    }
}
</code>```

Body:
So i am having an issue with the Azure Rest API for creating directories and files. I can list directories and files, which uses the same method to create the Authorization header, but i always get the 403 - Server failed to authenticate the request. The first block of code below is the code to obtain a list of directories which works.

String uri = string.Format($"https://{_azureClientSettings.StorageAccountName}.file.core.windows.net/{_azureClientSettings.StorageShare}?restype=directory&comp=list");

                // Set this to whatever payload you desire. Mine is null because i'm not passing anything in.
                Byte[] requestPayload = null;

                //Instantiate the request message with a null payload.
                using (var httpRequestMessage = new HttpRequestMessage(HttpMethod.Get, uri)
                { Content = (requestPayload == null) ? null : new ByteArrayContent(requestPayload) })
                {

                    // Add the request headers for x-ms-date and x-ms-version.
                    DateTime now = DateTime.UtcNow;
                    httpRequestMessage.Headers.Add("x-ms-date", now.ToString("R", CultureInfo.InvariantCulture));
                    httpRequestMessage.Headers.Add("x-ms-version", "2017-04-17");

                    // Add the authorization header.
                    httpRequestMessage.Headers.Authorization = AzureStorageAuthenticationHelper.GetAuthorizationHeader(
                       _azureClientSettings.StorageAccountName, _azureClientSettings.StorageAccountKey, now, httpRequestMessage);

                    // Send the request.
                    using (HttpResponseMessage httpResponseMessage = await _httpClientRepo.Instance().SendAsync(httpRequestMessage, CancellationToken.None))
                    {
                        if (httpResponseMessage.StatusCode == HttpStatusCode.OK)
                        {
                            ...
                        }
                    }
                }
            }

This block of code is the code i use in an attempt to create a directory, which fails.

Uri storageUri = new Uri($"https://{_azureClientSettings.StorageAccountName}.file.core.windows.net/{_azureClientSettings.StorageShare}/{directoryName}?restype=directory");

using (var httpRequestMessage = new HttpRequestMessage(HttpMethod.Put, storageUri)
{ Content = new StringContent("") })
{
                var now = DateTime.UtcNow;
                httpRequestMessage.Headers.Add("x-ms-date", now.ToString("R", CultureInfo.InvariantCulture));
                httpRequestMessage.Headers.Add("x-ms-version", "2017-04-17");
                httpRequestMessage.Headers.Add("x-ms-content-length", "200");
                httpRequestMessage.Headers.Add("x-ms-type", "file");

                // Add the authorization header.
                httpRequestMessage.Headers.Authorization = AzureStorageAuthenticationHelper.GetAuthorizationHeader(
                    _azureClientSettings.StorageAccountName, _azureClientSettings.StorageAccountKey, now, httpRequestMessage);

                // Send the request.
                using (var httpResponseMessage = await _httpClientRepo.Instance().SendAsync(httpRequestMessage, CancellationToken.None))
            {
               ...
            }
}

As i say, i have a very similar method for creating a file and that also fails with a 403.I have taken the authorization header creation from https://github.com/mstaples84/azurefileserviceauth/blob/4bce5c268cd9ce6c91d9e8723ce72eb5e0df3255/SimpleAzureFileServiceDemo/AzureStorageAuthenticationHelper.cs

Any help would be much appreciated.

Body:
As discussed in the comments, there was an issue with the code in AzureStorageAuthenticationHelper.

Here's the code I wrote that worked:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;
using Azure.Storage.Blobs;
using System.Net.Http;
using System.Globalization;
using System.Net.Http.Headers;
using System.Collections.Specialized;
using System.Web;
using System.Security.Cryptography;

namespace ConsoleApp1
{
    class Program
    {
        const string accountName = "myaccountname";
        const string accountKey = "myaccountkey";
        const string shareName = "test";
        const string directory = "test";

        static void Main(string[] args)
        {
            Uri storageUri = new Uri($"https://{accountName}.file.core.windows.net/{shareName}/{directory}?restype=directory");

            using (var httpRequestMessage = new HttpRequestMessage(HttpMethod.Put, storageUri)
            { Content = new StringContent("") })
            {
                var now = DateTime.UtcNow;
                httpRequestMessage.Headers.Add("x-ms-date", now.ToString("R", CultureInfo.InvariantCulture));
                httpRequestMessage.Headers.Add("x-ms-version", "2017-04-17");
                httpRequestMessage.Headers.Add("x-ms-content-length", "200");
                httpRequestMessage.Headers.Add("x-ms-type", "file");

                // Add the authorization header.
                httpRequestMessage.Headers.Authorization = AzureStorageAuthenticationHelper.GetAuthorizationHeader(
                    accountName, accountKey, now, httpRequestMessage);

                // Send the request.
                using (var response = new HttpClient().SendAsync(httpRequestMessage).GetAwaiter().GetResult())
                {
                    Console.WriteLine("Directory created successfully.");
                }
            }

        }
    }

    internal static class AzureStorageAuthenticationHelper
    {
        /// <summary>
        /// This creates the authorization header. This is required, and must be built
        ///   exactly following the instructions. This will return the authorization header
        ///   for most storage service calls.
        /// Create a string of the message signature and then encrypt it.
        /// </summary>
        /// <param name="storageAccountName">The name of the storage account to use.</param>
        /// <param name="storageAccountKey">The access key for the storage account to be used.</param>
        /// <param name="now">Date/Time stamp for now.</param>
        /// <param name="httpRequestMessage">The HttpWebRequest that needs an auth header.</param>
        /// <param name="ifMatch">Provide an eTag, and it will only make changes
        /// to a blob if the current eTag matches, to ensure you don't overwrite someone else's changes.</param>
        /// <param name="md5">Provide the md5 and it will check and make sure it matches the blob's md5.
        /// If it doesn't match, it won't return a value.</param>
        /// <returns></returns>
        internal static AuthenticationHeaderValue GetAuthorizationHeader(
           string storageAccountName, string storageAccountKey, DateTime now,
           HttpRequestMessage httpRequestMessage, string ifMatch = "", string md5 = "")
        {
            // This is the raw representation of the message signature.
            var method = httpRequestMessage.Method;

            // content length
            var contentLength = string.Empty;
            if (!(method == HttpMethod.Get || method == HttpMethod.Head))
            {
                var length = httpRequestMessage.Content?.Headers.ContentLength;

                if (length != null && length > 0)
                {
                    contentLength = length.ToString();
                }
            }

            String messageSignature = String.Format("{0}\n\n\n{1}\n{5}\n{7}\n{6}\n\n{2}\n\n\n\n{3}{4}",
                      method.ToString().ToUpper(),
                      contentLength,
                      ifMatch,
                      GetCanonicalizedHeaders(httpRequestMessage),
                      GetCanonicalizedResource(httpRequestMessage.RequestUri, storageAccountName),
                      md5,
                      string.Empty,
                      httpRequestMessage.Content?.Headers.ContentType.ToString() ?? string.Empty);

            // Now turn it into a byte array.
            var signatureBytes = Encoding.UTF8.GetBytes(messageSignature);

            // Create the HMACSHA256 version of the storage key.
            var SHA256 = new HMACSHA256(Convert.FromBase64String(storageAccountKey));

            // Compute the hash of the SignatureBytes and convert it to a base64 string.
            var signature = Convert.ToBase64String(SHA256.ComputeHash(signatureBytes));

            // This is the actual header that will be added to the list of request headers.
            // You can stop the code here and look at the value of 'authHV' before it is returned.
            var authHV = new AuthenticationHeaderValue("SharedKey",
                storageAccountName + ":" + signature);
            return authHV;
        }

        /// <summary>
        /// Put the headers that start with x-ms in a list and sort them.
        /// Then format them into a string of [key:value\n] values concatenated into one string.
        /// (Canonicalized Headers = headers where the format is standardized).
        /// </summary>
        /// <param name="httpRequestMessage">The request that will be made to the storage service.</param>
        /// <returns>Error message; blank if okay.</returns>
        private static string GetCanonicalizedHeaders(HttpRequestMessage httpRequestMessage)
        {
            var headers = from kvp in httpRequestMessage.Headers
                          where kvp.Key.StartsWith("x-ms-", StringComparison.OrdinalIgnoreCase)
                          orderby kvp.Key
                          select new { Key = kvp.Key.ToLowerInvariant(), kvp.Value };

            StringBuilder sb = new StringBuilder();

            // Create the string in the right format; this is what makes the headers "canonicalized" --
            //   it means put in a standard format. http://en.wikipedia.org/wiki/Canonicalization
            foreach (var kvp in headers)
            {
                StringBuilder headerBuilder = new StringBuilder(kvp.Key);
                char separator = ':';

                // Get the value for each header, strip out \r\n if found, then append it with the key.
                foreach (string headerValues in kvp.Value)
                {
                    string trimmedValue = headerValues.TrimStart().Replace("\r\n", String.Empty);
                    headerBuilder.Append(separator).Append(trimmedValue);

                    // Set this to a comma; this will only be used
                    //   if there are multiple values for one of the headers.
                    separator = ',';
                }
                sb.Append(headerBuilder.ToString()).Append("\n");
            }
            return sb.ToString();
        }

        /// <summary>
        /// This part of the signature string represents the storage account
        ///   targeted by the request. Will also include any additional query parameters/values.
        /// For ListContainers, this will return something like this:
        ///   /storageaccountname/\ncomp:list
        /// </summary>
        /// <param name="address">The URI of the storage service.</param>
        /// <param name="accountName">The storage account name.</param>
        /// <returns>String representing the canonicalized resource.</returns>
        private static string GetCanonicalizedResource(Uri address, string storageAccountName)
        {
            // The absolute path is "/" because for we're getting a list of containers.
            StringBuilder sb = new StringBuilder("/").Append(storageAccountName).Append(address.AbsolutePath);

            // Address.Query is the resource, such as "?comp=list".
            // This ends up with a NameValueCollection with 1 entry having key=comp, value=list.
            // It will have more entries if you have more query parameters.
            NameValueCollection values = HttpUtility.ParseQueryString(address.Query);

            foreach (var item in values.AllKeys.OrderBy(k => k))
            {
                sb.Append('\n').Append(item).Append(':').Append(values[item]);
            }

            return sb.ToString();

        }
    }
}


来源: stackexchange

问:
StreamBuild: stream, calling a method that returns a Firestore Stream does not retrieve data until update
I'm hoping that someone can explain why there is different in behavior when explicitly calling Firestore.instance.collection('data').snapshots() vs calling a method that contain Firestore.instance.collection('data').snapshots() and returns a Stream.

Calling a method that contains Firestore.instance.collection('data').snapshots() only grabs the data snapshot after a change is made to the firestore data.

```<code>class GlobalAppModel extends Model{
......//other global data elements

  Stream getDataStreamSnapshots(){
    Firestore.instance.collection('data').snapshots();
  }
}
</code>```

```<code>class DataDetailWidget2 extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    dataStream = AppModel.of(context);
    ....
    body: Container(
        child: StreamBuilder(
          stream: Firestore.instance.collection('data').snapshots(), //This works great.
          //stream: dataStream.getDataStreamSnapshots(), //This does not grab a snapshot until firestore is updated.
          builder: (context, snapshot) {
            .....
          }

    ....
  }

}
</code>```

答:
You are just missing return keyword in your getDataStreamSnapshots method.</p>

```<code>class GlobalAppModel extends Model{
......//other global data elements

  Stream getDataStreamSnapshots(){
    return Firestore.instance.collection('data').snapshots(); // return added
  }
}
</code>```

ContentLicense: CC BY-SA 4.0

Body:
I'm hoping that someone can explain why there is different in behavior when explicitly calling Firestore.instance.collection('data').snapshots() vs calling a method that contain Firestore.instance.collection('data').snapshots() and returns a Stream.

Calling a method that contains Firestore.instance.collection('data').snapshots() only grabs the data snapshot after a change is made to the firestore data.

class GlobalAppModel extends Model{
......//other global data elements

  Stream getDataStreamSnapshots(){
    Firestore.instance.collection('data').snapshots();
  }
}

class DataDetailWidget2 extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    dataStream = AppModel.of(context);
    ....
    body: Container(
        child: StreamBuilder(
          stream: Firestore.instance.collection('data').snapshots(), //This works great.
          //stream: dataStream.getDataStreamSnapshots(), //This does not grab a snapshot until firestore is updated.
          builder: (context, snapshot) {
            .....
          }

    ....
  }

}

Body:
You are just missing return keyword in your getDataStreamSnapshots method.

class GlobalAppModel extends Model{
......//other global data elements

  Stream getDataStreamSnapshots(){
    return Firestore.instance.collection('data').snapshots(); // return added
  }
}


问:
How I get ExoPlayer to resume a video in my Activity's onStart() method?
I'm using ExoPlayer to play some mp4's from a URL. When the user click's the home button, or anything that causes the app to be removed from the user's view and then comes back to my app (and video activity) I want the video to resume where it left off. I tried implementing this by saving the video position in onStop() and then rebuilding the player and using seekTo() in onStart(). I have a check to see if my current exoplayer is null in onStart(), this check never passes however, so I think this is where the problem lies. How it's coded now my video never resumes. If I leave the app by pressing the home button onStop() gets called and then onStart() will get called when I go back into my app, however the video player remains black and never plays the video. If I remove the null check I get two instances of the video playing whenever I start a video from the main activity because it gets called both in onCreate() and onStart(). Is there a better method for getting the functionality that I want? Any help is appreciated!

```<code>public class VideoActivity extends AppCompatActivity {

    private SimpleExoPlayer exoPlayer;
    private SimpleExoPlayerView simpleExoPlayerView;
    private long playerPosition;
    private String mp4Url;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.player_activity);

        // Get the Intent that started this activity and extract the video url
        Intent intent = getIntent();
        mp4Url = intent.getStringExtra(MainActivity.VIDEO_URL);
        // Create an exoplayer instance and start playing video
        buildPlayer(mp4Url);

    }

    private void buildPlayer(String mp4Url) {
        // Create a default TrackSelector
        Handler mainHandler = new Handler();
        BandwidthMeter bandwidthMeter = new DefaultBandwidthMeter();
        TrackSelection.Factory videoTrackSelectionFactory = new AdaptiveTrackSelection.Factory(bandwidthMeter);
        TrackSelector trackSelector = new DefaultTrackSelector(videoTrackSelectionFactory);

        // Create the player
        exoPlayer = ExoPlayerFactory.newSimpleInstance(this, trackSelector); // no LoadControl?
        simpleExoPlayerView = new SimpleExoPlayerView(this);
        simpleExoPlayerView = (SimpleExoPlayerView) findViewById(R.id.player_view);

        // Set media controller
        simpleExoPlayerView.setUseController(true);
        simpleExoPlayerView.requestFocus();

        // Bind player to the view
        simpleExoPlayerView.setPlayer(exoPlayer);

        // Create Uri from video location
        // TODO: should this be in some network class? Should I be appending APIKEY here?
        Uri mp4Uri = Uri.parse(mp4Url + "?api_key=" + BuildConfig.GIANTBOMB_API_KEY);
        Timber.v("Video url with api key: " + mp4Uri.toString());

        // Create another bandwidth meter for bandwidth during playback (not strictly necessary)
        DefaultBandwidthMeter playbackBandwidthMeter = new DefaultBandwidthMeter();

        // DataSourceFactory to produce DataSource instances through which media data is loaded
        DefaultDataSourceFactory dataSourceFactory = new DefaultDataSourceFactory(this,
                Util.getUserAgent(this, "GiantBombForAndroid"),
                playbackBandwidthMeter);

        // Produces Extractor instances for parsing the media data
        ExtractorsFactory extractorsFactory = new DefaultExtractorsFactory();

        ExtractorMediaSource.EventListener eventListener = new ExtractorMediaSource.EventListener() {
            @Override
            public void onLoadError(IOException error) {
                Timber.e("Error loading video from source");
            }
        };

        final MediaSource videoSource = new ExtractorMediaSource(mp4Uri,
                dataSourceFactory,
                extractorsFactory,
                mainHandler,
                eventListener);

        exoPlayer.prepare(videoSource);

        exoPlayer.addListener(new ExoPlayer.EventListener() {
            @Override
            public void onLoadingChanged(boolean isLoading) {
                Timber.v("Listener-onLoadingChanged...");

            }

            @Override
            public void onPlayerStateChanged(boolean playWhenReady, int playbackState) {
                Timber.v("Listener-onPlayerStateChanged...");

            }

            @Override
            public void onTimelineChanged(Timeline timeline, Object manifest) {
                Timber.v("Listener-onTimelineChanged...");

            }

            @Override
            public void onTracksChanged(TrackGroupArray trackGroups, TrackSelectionArray trackSelections) {
                // TODO: Do I need anything here?
            }

            @Override
            public void onPlayerError(ExoPlaybackException error) {
                Timber.v("Listener-onPlayerError...");
                exoPlayer.stop();
                exoPlayer.prepare(videoSource);
                exoPlayer.setPlayWhenReady(true);
            }

            @Override
            public void onPositionDiscontinuity() {
                Timber.v("Listener-onPositionDiscontinuity...");

            }

            @Override
            public void onPlaybackParametersChanged(PlaybackParameters playbackParameters) {
                // TODO: Do I need anything here?
            }
        });
        exoPlayer.setPlayWhenReady(true);
    }

    @Override
    protected void onStart() {
        super.onStart();
        Timber.v("onStart()...");
        if (exoPlayer == null) {
            Timber.v("No exoplayer instance, recreating...");
            buildPlayer(mp4Url);
            exoPlayer.seekTo(playerPosition);
        }
    }

    @Override
    protected void onStop(){
        super.onStop();
        Timber.v("onStop()...");
        //TODO: pull player creation code into it's own method so it can be called here as well
        playerPosition = exoPlayer.getCurrentPosition();
        exoPlayer.release();
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        Timber.v("onDestroy()...");
        exoPlayer.release();
    }
}
</code>```

答:
There is no need to reinit player again. The following code is pretty enough:</p>

```<code> @Override
 protected void onPause() {
     super.onPause();
     if (player!=null) {
         player.stop();
          mLastPosition = player.getCurrentPosition();
     }
 }

 @Override
 protected void onResume() {
     super.onResume();
     //initiatePlayer();
     if(mLastPosition!=0 && player!=null){
         player.seekTo(mLastPosition);
     }
 }
</code>```

ContentLicense: CC BY-SA 3.0

Body:
I'm using ExoPlayer to play some mp4's from a URL. When the user click's the home button, or anything that causes the app to be removed from the user's view and then comes back to my app (and video activity) I want the video to resume where it left off. I tried implementing this by saving the video position in onStop() and then rebuilding the player and using seekTo() in onStart(). I have a check to see if my current exoplayer is null in onStart(), this check never passes however, so I think this is where the problem lies. How it's coded now my video never resumes. If I leave the app by pressing the home button onStop() gets called and then onStart() will get called when I go back into my app, however the video player remains black and never plays the video. If I remove the null check I get two instances of the video playing whenever I start a video from the main activity because it gets called both in onCreate() and onStart(). Is there a better method for getting the functionality that I want? Any help is appreciated!

public class VideoActivity extends AppCompatActivity {

    private SimpleExoPlayer exoPlayer;
    private SimpleExoPlayerView simpleExoPlayerView;
    private long playerPosition;
    private String mp4Url;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.player_activity);

        // Get the Intent that started this activity and extract the video url
        Intent intent = getIntent();
        mp4Url = intent.getStringExtra(MainActivity.VIDEO_URL);
        // Create an exoplayer instance and start playing video
        buildPlayer(mp4Url);

    }

    private void buildPlayer(String mp4Url) {
        // Create a default TrackSelector
        Handler mainHandler = new Handler();
        BandwidthMeter bandwidthMeter = new DefaultBandwidthMeter();
        TrackSelection.Factory videoTrackSelectionFactory = new AdaptiveTrackSelection.Factory(bandwidthMeter);
        TrackSelector trackSelector = new DefaultTrackSelector(videoTrackSelectionFactory);

        // Create the player
        exoPlayer = ExoPlayerFactory.newSimpleInstance(this, trackSelector); // no LoadControl?
        simpleExoPlayerView = new SimpleExoPlayerView(this);
        simpleExoPlayerView = (SimpleExoPlayerView) findViewById(R.id.player_view);

        // Set media controller
        simpleExoPlayerView.setUseController(true);
        simpleExoPlayerView.requestFocus();

        // Bind player to the view
        simpleExoPlayerView.setPlayer(exoPlayer);

        // Create Uri from video location
        // TODO: should this be in some network class? Should I be appending APIKEY here?
        Uri mp4Uri = Uri.parse(mp4Url + "?api_key=" + BuildConfig.GIANTBOMB_API_KEY);
        Timber.v("Video url with api key: " + mp4Uri.toString());

        // Create another bandwidth meter for bandwidth during playback (not strictly necessary)
        DefaultBandwidthMeter playbackBandwidthMeter = new DefaultBandwidthMeter();

        // DataSourceFactory to produce DataSource instances through which media data is loaded
        DefaultDataSourceFactory dataSourceFactory = new DefaultDataSourceFactory(this,
                Util.getUserAgent(this, "GiantBombForAndroid"),
                playbackBandwidthMeter);

        // Produces Extractor instances for parsing the media data
        ExtractorsFactory extractorsFactory = new DefaultExtractorsFactory();

        ExtractorMediaSource.EventListener eventListener = new ExtractorMediaSource.EventListener() {
            @Override
            public void onLoadError(IOException error) {
                Timber.e("Error loading video from source");
            }
        };

        final MediaSource videoSource = new ExtractorMediaSource(mp4Uri,
                dataSourceFactory,
                extractorsFactory,
                mainHandler,
                eventListener);

        exoPlayer.prepare(videoSource);

        exoPlayer.addListener(new ExoPlayer.EventListener() {
            @Override
            public void onLoadingChanged(boolean isLoading) {
                Timber.v("Listener-onLoadingChanged...");

            }

            @Override
            public void onPlayerStateChanged(boolean playWhenReady, int playbackState) {
                Timber.v("Listener-onPlayerStateChanged...");

            }

            @Override
            public void onTimelineChanged(Timeline timeline, Object manifest) {
                Timber.v("Listener-onTimelineChanged...");

            }

            @Override
            public void onTracksChanged(TrackGroupArray trackGroups, TrackSelectionArray trackSelections) {
                // TODO: Do I need anything here?
            }

            @Override
            public void onPlayerError(ExoPlaybackException error) {
                Timber.v("Listener-onPlayerError...");
                exoPlayer.stop();
                exoPlayer.prepare(videoSource);
                exoPlayer.setPlayWhenReady(true);
            }

            @Override
            public void onPositionDiscontinuity() {
                Timber.v("Listener-onPositionDiscontinuity...");

            }

            @Override
            public void onPlaybackParametersChanged(PlaybackParameters playbackParameters) {
                // TODO: Do I need anything here?
            }
        });
        exoPlayer.setPlayWhenReady(true);
    }

    @Override
    protected void onStart() {
        super.onStart();
        Timber.v("onStart()...");
        if (exoPlayer == null) {
            Timber.v("No exoplayer instance, recreating...");
            buildPlayer(mp4Url);
            exoPlayer.seekTo(playerPosition);
        }
    }

    @Override
    protected void onStop(){
        super.onStop();
        Timber.v("onStop()...");
        //TODO: pull player creation code into it's own method so it can be called here as well
        playerPosition = exoPlayer.getCurrentPosition();
        exoPlayer.release();
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        Timber.v("onDestroy()...");
        exoPlayer.release();
    }
}

Body:
There is no need to reinit player again. The following code is pretty enough:

 @Override
 protected void onPause() {
     super.onPause();
     if (player!=null) {
         player.stop();
          mLastPosition = player.getCurrentPosition();
     }
 }

 @Override
 protected void onResume() {
     super.onResume();
     //initiatePlayer();
     if(mLastPosition!=0 && player!=null){
         player.seekTo(mLastPosition);
     }
 }


问:
How to change blank fields to null in express js
I want to get all request body params as null if param is blank. Is there any way in the express js.

```<code>{
  username: " ",
  password: ""
}
</code>```

// Get it as

```<code>{
  username: null,
  password: null
}
</code>```

答:
Maybe you want to use this function below:

let objects = {
    username: ' ',
    password: '',
    testing: [
      {
        id: ' ',
        testing: 'testing'
      }
    ],
    obj: {
      key: ' ',
      value: 'value'
    }
}

function setEmptyToNull(obj) {
    Object.keys(obj).forEach(key => {
        if (Array.isArray(obj[key])) {
            obj[key].map(o => {
                if (typeof o === 'object') {
                    setEmptyToNull(o);
                }
            })
        } else if(typeof obj[key] ==='string') {
          if(obj[key].trim() === '') {
            obj[key] = null;
          }
        } else if(typeof obj[key] === 'object') {
          setEmptyToNull(obj[key]);
        }
    });
    return obj;
}

console.log(setEmptyToNull(objects));```
</div>
</div>
</p>

<p>Now, <strong>if you want to use in your express application</strong>, then you can set that function in your custom <code>middleware</code>. It's will looks like this code below:</p>

<pre class="lang-js prettyprint-override"><code>app.use((req, res, next) => {
  if(req.body) {
    setEmptyToNull(req.body);
  };
  next();
});
</code>```

After you set your custom middleware, now each value of key in your req.body, if it's ' ' then will be set to null.

I hope it can help you.

Body:
I want to get all request body params as null if param is blank. Is there any way in the express js.

{
  username: " ",
  password: ""
}

// Get it as

{
  username: null,
  password: null
}

Body:
Maybe you want to use this function below:

let objects = {
    username: ' ',
    password: '',
    testing: [
      {
        id: ' ',
        testing: 'testing'
      }
    ],
    obj: {
      key: ' ',
      value: 'value'
    }
}

function setEmptyToNull(obj) {
    Object.keys(obj).forEach(key => {
        if (Array.isArray(obj[key])) {
            obj[key].map(o => {
                if (typeof o === 'object') {
                    setEmptyToNull(o);
                }
            })
        } else if(typeof obj[key] ==='string') {
          if(obj[key].trim() === '') {
            obj[key] = null;
          }
        } else if(typeof obj[key] === 'object') {
          setEmptyToNull(obj[key]);
        }
    });
    return obj;
}

console.log(setEmptyToNull(objects));

Now, if you want to use in your express application, then you can set that function in your custom middleware. It's will looks like this code below:

app.use((req, res, next) => {
  if(req.body) {
    setEmptyToNull(req.body);
  };
  next();
});

After you set your custom middleware, now each value of key in your req.body, if it's ' ' then will be set to null.

I hope it can help you.


问:
How to avoid casting to a specific interface

Background info

I have a set of interfaces/classes as follows. For the sake of simplicity imagine more properties, collections etc.

interface IMaster
{
//Some properties
}

interface IB : IMaster
{
    string PropOnA { get; set }
}
interface IC : IMaster
{
    string PropOnB { get; set }
}

class B : IB
class C : IC
...
```

<p>These contracts were designed to store data(which is held in a slightly different format in each case). There is a lot of code that uses these contracts to get the data, format it, process it, write etc.
We have developed an entire library that does not see the concrete implementations(B,C) of any of these contracts by inverting control and allow the user to use our 'default implementations' for each contract or just loading in their own. We have registry where the user can register a different implementation.</p>

<p>To this end I have implemented a kind of strategy pattern where there exists a strategy for each contract type based on the task at hand. For the sake of simplicity lets say the task is <strong>writing</strong>, in reality it is much more complicated.</p>

```interface IWriteStrategy
{
    public Write(IMaster thing);
}

class WriterA : IWriteStrategy

class WriterB : IWriteStrategy

etc
```

<p>The above concrete strategies are also never 'seen' in our library, the client must register their own implementation or our default version. </p>

<h3>Design flaw??</h3>

<p>I am not liking the cast in every strategy that is now necessary.</p>

```public classWriterA : IWriteStrategy
{
    public void Write(IMaster thing)
    {
        if(thing is IA thingA)
        //do some work
    }
}

public classWriterB : IWriteStrategy
{
    public void Write(IMaster thing)
    {
        if(thing is IB thingB)
        //do some work
    }
}
```

<p>What we want to do is be able to loop through a list of <code>IMaster</code> objects and run some operations.</p>

```foreach(var thing in Things)
{
    var strategy = GetStrategy(thing.GetType());  //this gets the strategy object from our `registry` if one exists
    strategy.Execute(thing);
}
```

The above design allows this but there seems to be a flaw which I cant for the life of me spot a solution to. We have to cast to the specific interface within each strategy implementation.

I have tried with generics, but just cant seem to nail it.

Question

What would be a better way of designing this to avoid the cast but still be able to loop through a list of IMaster things and treat them the same? Or is the cast absolutely necessary here?

I am trying to follow a SOLID design but feel the cast is messing with this as the client implementing the strategies will have to do the cast in order to get anything to work within the Write method.

[Edit]
I have updated the classes implementing the IWriteStrategy.

答:
what about this, you will have all your casts in one strategy factory method:</p>

```<code> public interface IWriterStrategy
{
    void Execute();
}

public class WriterA : IWriterStrategy
{
    private readonly IA _thing;

    public WriterA(IA thing)
    {
        _thing = thing;
    }
    public void Execute()
    {
        Console.WriteLine(_thing.PropOnA);
    }
}

public class WriterB : IWriterStrategy
{
    private readonly IB _thing;
    public WriterB(IB thing)
    {
        _thing = thing;
    }
    public void Execute()
    {
        Console.WriteLine(_thing.PropOnB);
    }
}

public static class WriterFactory
{
    public static List<(Type Master, Type Writer)> RegisteredWriters = new List<(Type Master, Type Writer)>
        {
           (typeof(IA),  typeof(WriterA)),
           (typeof(IB),  typeof(WriterB))
        };
    public static IWriterStrategy GetStrategy(IMaster thing)
    {
        (Type Master, Type Writer) writerTypeItem = RegisteredWriters.Find(x => x.Master.IsAssignableFrom(thing.GetType()));
        if (writerTypeItem.Master != null)
        {
            return (IWriterStrategy)Activator.CreateInstance(writerTypeItem.Writer, thing);
        }
        throw new Exception("Strategy not found!");
    }
}

public interface IMaster
{
    //Some properties
}

public interface IA : IMaster
{
    string PropOnA { get; set; }
}

public interface IB : IMaster
{
    string PropOnB { get; set; }
}

public interface IC : IMaster
{
    string PropOnC { get; set; }
}

public class ThingB : IB
{
    public string PropOnB { get => "IB"; set => throw new NotImplementedException(); }
}

public class ThingA : IA
{
    public string PropOnA { get => "IA"; set => throw new NotImplementedException(); }
}

public class ThingC : IC
{
    public string PropOnC { get => "IC"; set => throw new NotImplementedException(); }
}

internal static class Program
{
    private static void Main(string[] args)
    {
        var things = new List<IMaster> {
            new ThingA(),
            new ThingB()//,
            //new ThingC()
        };

        foreach (var thing in things)
        {
            var strategy = WriterFactory.GetStrategy(thing);  //this gets the strategy object from our `registry` if one exists
            strategy.Execute();
        }
    }
}
</code>```

Body:
Background info

I have a set of interfaces/classes as follows. For the sake of simplicity imagine more properties, collections etc.

interface IMaster
{
//Some properties
}

interface IB : IMaster
{
    string PropOnA { get; set }
}
interface IC : IMaster
{
    string PropOnB { get; set }
}

class B : IB
class C : IC
...

These contracts were designed to store data(which is held in a slightly different format in each case). There is a lot of code that uses these contracts to get the data, format it, process it, write etc.
We have developed an entire library that does not see the concrete implementations(B,C) of any of these contracts by inverting control and allow the user to use our 'default implementations' for each contract or just loading in their own. We have registry where the user can register a different implementation.

To this end I have implemented a kind of strategy pattern where there exists a strategy for each contract type based on the task at hand. For the sake of simplicity lets say the task is writing, in reality it is much more complicated.

interface IWriteStrategy
{
    public Write(IMaster thing);
}

class WriterA : IWriteStrategy

class WriterB : IWriteStrategy

etc

The above concrete strategies are also never 'seen' in our library, the client must register their own implementation or our default version.

Design flaw??

I am not liking the cast in every strategy that is now necessary.

public classWriterA : IWriteStrategy
{
    public void Write(IMaster thing)
    {
        if(thing is IA thingA)
        //do some work
    }
}

public classWriterB : IWriteStrategy
{
    public void Write(IMaster thing)
    {
        if(thing is IB thingB)
        //do some work
    }
}

What we want to do is be able to loop through a list of IMaster objects and run some operations.

foreach(var thing in Things)
{
    var strategy = GetStrategy(thing.GetType());  //this gets the strategy object from our `registry` if one exists
    strategy.Execute(thing);
}

The above design allows this but there seems to be a flaw which I cant for the life of me spot a solution to. We have to cast to the specific interface within each strategy implementation.

I have tried with generics, but just cant seem to nail it.

Question

What would be a better way of designing this to avoid the cast but still be able to loop through a list of IMaster things and treat them the same? Or is the cast absolutely necessary here?

I am trying to follow a SOLID design but feel the cast is messing with this as the client implementing the strategies will have to do the cast in order to get anything to work within the Write method.

[Edit]
I have updated the classes implementing the IWriteStrategy.

Body:
what about this, you will have all your casts in one strategy factory method:

 public interface IWriterStrategy
{
    void Execute();
}

public class WriterA : IWriterStrategy
{
    private readonly IA _thing;

    public WriterA(IA thing)
    {
        _thing = thing;
    }
    public void Execute()
    {
        Console.WriteLine(_thing.PropOnA);
    }
}

public class WriterB : IWriterStrategy
{
    private readonly IB _thing;
    public WriterB(IB thing)
    {
        _thing = thing;
    }
    public void Execute()
    {
        Console.WriteLine(_thing.PropOnB);
    }
}

public static class WriterFactory
{
    public static List<(Type Master, Type Writer)> RegisteredWriters = new List<(Type Master, Type Writer)>
        {
           (typeof(IA),  typeof(WriterA)),
           (typeof(IB),  typeof(WriterB))
        };
    public static IWriterStrategy GetStrategy(IMaster thing)
    {
        (Type Master, Type Writer) writerTypeItem = RegisteredWriters.Find(x => x.Master.IsAssignableFrom(thing.GetType()));
        if (writerTypeItem.Master != null)
        {
            return (IWriterStrategy)Activator.CreateInstance(writerTypeItem.Writer, thing);
        }
        throw new Exception("Strategy not found!");
    }
}

public interface IMaster
{
    //Some properties
}

public interface IA : IMaster
{
    string PropOnA { get; set; }
}

public interface IB : IMaster
{
    string PropOnB { get; set; }
}

public interface IC : IMaster
{
    string PropOnC { get; set; }
}

public class ThingB : IB
{
    public string PropOnB { get => "IB"; set => throw new NotImplementedException(); }
}

public class ThingA : IA
{
    public string PropOnA { get => "IA"; set => throw new NotImplementedException(); }
}

public class ThingC : IC
{
    public string PropOnC { get => "IC"; set => throw new NotImplementedException(); }
}

internal static class Program
{
    private static void Main(string[] args)
    {
        var things = new List<IMaster> {
            new ThingA(),
            new ThingB()//,
            //new ThingC()
        };

        foreach (var thing in things)
        {
            var strategy = WriterFactory.GetStrategy(thing);  //this gets the strategy object from our `registry` if one exists
            strategy.Execute();
        }
    }
}


问:
How do i retrieve images from folder which is linked to an item id?
The main issue is with the model, i cant figure out how to join the two tables so that i can display an item with its image  which are stored in different locations.
model

```<code>         $this->db->select('bs_items.id, bs_items.description, bs_items.title,
         bs_items.touch_count,bs_items.price');
         $this->db->from('core_images');
         $this->db->join('bs_items', 'core_images.img_parent_id =
         bs_items.id');
         $this->db->order_by('bs_items.touch_count', 'desc');
         $this->db->from('bs_items');
</code>```

Controller:

```<code>            this->load->model('Popular_car');
            $this->load->model('Recent_car');
            $data['popular_cars']= $this->Popular_car->popular_car();
            $data['recent_cars']=$this->Recent_car->get_listing();
            $this->load->view('templates/header');
            $this->load->view('pages/home', $data);
            $this->load->view('pages/home_recent', $data);
            $this->load->view('templates/footer');

</code>```

答:
Please update your question with some code you have done , or database structure. i'm giving you the answer based on what i understood using your given code snippet.

Model

```<code>function get_items()
{
     $this->db->select('*');
     $this->db->from('core_images');
     $this->db->join('bs_items', 'core_images.img_parent_id =
     bs_items.id');
     $this->db->order_by('bs_items.touch_count', 'desc');
     $query = $this->db->get();
     return $query->result();
}
</code>```

Controller

```<code>function get_allitems()
{
     $this->load->model('model_name');
     $data['items'] = $this->model_name->get_items();
     $this->load->view('view_name', $data);
}
</code>```

View

```<code><?php foreach ($items as $row): ?>

   <h1><?php echo $row->title;?></h1>
   <p><?php echo $row->touch_count;?></p>
   <p><?php echo $row->price;?></p>
   <p><?php echo $row->description;?></p>
   <img src="<?php echo base_url().'path_of_image/'.$row->image_from_db; ?>

<?php endforeach; ?>
</code>```

Body:
The main issue is with the model, i cant figure out how to join the two tables so that i can display an item with its image  which are stored in different locations.
model

         $this->db->select('bs_items.id, bs_items.description, bs_items.title,
         bs_items.touch_count,bs_items.price');
         $this->db->from('core_images');
         $this->db->join('bs_items', 'core_images.img_parent_id =
         bs_items.id');
         $this->db->order_by('bs_items.touch_count', 'desc');
         $this->db->from('bs_items');

Controller:

            this->load->model('Popular_car');
            $this->load->model('Recent_car');
            $data['popular_cars']= $this->Popular_car->popular_car();
            $data['recent_cars']=$this->Recent_car->get_listing();
            $this->load->view('templates/header');
            $this->load->view('pages/home', $data);
            $this->load->view('pages/home_recent', $data);
            $this->load->view('templates/footer');

Body:
Please update your question with some code you have done , or database structure. i'm giving you the answer based on what i understood using your given code snippet.

Model

function get_items()
{
     $this->db->select('*');
     $this->db->from('core_images');
     $this->db->join('bs_items', 'core_images.img_parent_id =
     bs_items.id');
     $this->db->order_by('bs_items.touch_count', 'desc');
     $query = $this->db->get();
     return $query->result();
}

Controller

function get_allitems()
{
     $this->load->model('model_name');
     $data['items'] = $this->model_name->get_items();
     $this->load->view('view_name', $data);
}

View

<?php foreach ($items as $row): ?>

   <h1><?php echo $row->title;?></h1>
   <p><?php echo $row->touch_count;?></p>
   <p><?php echo $row->price;?></p>
   <p><?php echo $row->description;?></p>
   <img src="<?php echo base_url().'path_of_image/'.$row->image_from_db; ?>

<?php endforeach; ?>


问:
link with target="_blank" does not open in new tab in Chrome
On this website, the top accordion navigation contains an element called "Foundation": (screenshot).

This element is produced by HTML code:

```<code><a href="http://www.foracure.org.au" target="_blank" style="width: 105px;"></a>
</code>```

However, in Chrome, when you click on this element, the new website does not open in a new tab.

Can you please tell me why? Thank you.

答:
most simple answer

```<code><a onclick="window.open(this.href,'_blank');return false;" href="http://www.foracure.org.au">Some Other Site</a>
</code>```

it will work

Body:
On this website, the top accordion navigation contains an element called "Foundation": (screenshot).

This element is produced by HTML code:

However, in Chrome, when you click on this element, the new website does not open in a new tab.

Can you please tell me why? Thank you.

Body:
most simple answer

<a onclick="window.open(this.href,'_blank');return false;" href="http://www.foracure.org.au">Some Other Site</a>

it will work


问:
utag for tealium is being coverted to file:// in ionic 3 after building into an Android app
I have a utag_src with "https://......" (I have also tried "//tags.tiqcdn...." without the protocol) but after being called the first time, it sends 2 more times with http://

http://tags.tiqcdn.com/utag/company/appname/environment/utag.3.js?event

This works fine on browser but after building it into an Android App, it's being converted to file:// and that's throwing me an error and I am no longer able to track things.

file://tags.tiqcdn.com/utag/company/appname/environment/utag.3.js?event

Anyone know a way to either keep it in https or prevent it from converting into file:// in android?

答:
It sounds like you are trying to use utag.js natively within Ionic.

In order to correctly get Tealium to work within your Ionic app, you should use the Tealium plugin for Ionic:

https://ionicframework.com/docs/native/tealium


问:
How can I use preg_match in jQuery?
Can I use preg_match to validate phone number in jQuery? Here is my code which does not work:

```<code>if (!preg_match("/^[0-9]{3}-|\s[0-9]{3}-|\s[0-9]{4}$/", phone.val() ))  {
            phone.addClass("needsfilled");
            phone.val(phonerror);
        }
</code>```

HTML
<input id="phone" type="text" value=""  name="phone" />

答:
Javascript includes a regular expression engine, which is accessed via the string.match(), string.replace() and string.split() functions.

For example:

```<code>var mystring = "this is a sentence";
mystring = mystring.replace(/sentence/,'string');

var matches = mystring.match(/\b\w+\b/);
</code>```

That should provide you with essentially the same functionality as preg_match().

So to do the same validation as the preg_match in your question:

```<code>if(!phone.val().match(/^[0-9]{3}-|\s[0-9]{3}-|\s[0-9]{4}$/)) {
     phone.addClass("needsfilled");
     phone.val(phonerror);
}
</code>```

If you absolutely insist on having a function called preg_match() which works exactly like the PHP version, there is a project called PHPJS, which aims to implement PHP functions in Javascript. A quick look at their site shows that although they don't currently have a fully working preg_match() implementation, they have an unfinished implementation which you may want to look at. But frankly, the built-in Javascript .match() function should be more than sufficient.

Title: How can I use preg_match in jQuery?

Body:
Can I use preg_match to validate phone number in jQuery? Here is my code which does not work:

if (!preg_match("/^[0-9]{3}-|\s[0-9]{3}-|\s[0-9]{4}$/", phone.val() ))  {
            phone.addClass("needsfilled");
            phone.val(phonerror);
        }

HTML
<input id="phone" type="text" value=""  name="phone" />

Body:
Javascript includes a regular expression engine, which is accessed via the string.match(), string.replace() and string.split() functions.

For example:

var mystring = "this is a sentence";
mystring = mystring.replace(/sentence/,'string');

var matches = mystring.match(/\b\w+\b/);

That should provide you with essentially the same functionality as preg_match().

So to do the same validation as the preg_match in your question:

if(!phone.val().match(/^[0-9]{3}-|\s[0-9]{3}-|\s[0-9]{4}$/)) {
     phone.addClass("needsfilled");
     phone.val(phonerror);
}

If you absolutely insist on having a function called preg_match() which works exactly like the PHP version, there is a project called PHPJS, which aims to implement PHP functions in Javascript. A quick look at their site shows that although they don't currently have a fully working preg_match() implementation, they have an unfinished implementation which you may want to look at. But frankly, the built-in Javascript .match() function should be more than sufficient.


问:
C++ How is release-and-acquire achieved on x86 only using MOV?
This question is a follow-up/clarification to this:

Does the MOV x86 instruction implement a C++11 memory_order_release atomic store?

This states the MOV assembly instruction is sufficient to perform acquire-release semantics on x86. We do not need LOCK, fences or xchg etc. However, I am struggling to understand how this works.

Intel doc Vol 3A Chapter 8 states:

https://software.intel.com/sites/default/files/managed/7c/f1/253668-sdm-vol-3a.pdf

In a single-processor (core) system....

Reads are not reordered with other reads.

Writes are not reordered with older reads.

Writes to memory are not reordered with other writes, with the following exceptions:

but this is for a single core. The multi-core section does not seem to mention how loads are enforced:

In a multiple-processor system, the following ordering principles apply:

Individual processors use the same ordering principles as in a single-processor system.

Writes by a single processor are observed in the same order by all processors.

Writes from an individual processor are NOT ordered with respect to the writes from other processors.

Memory ordering obeys causality (memory ordering respects transitive visibility).

Any two stores are seen in a consistent order by processors other than those performing the stores

Locked instructions have a total order.

So how can MOV alone can facilitate acquire-release?

答:
Refreshing the semantics of acquire and release (quoting cppreference rather than the standard, because it's what I have on hand - the standard is more...verbose, here):

memory_order_acquire: A load operation with this memory order performs the acquire operation on the affected memory location: no reads or writes in the current thread can be reordered before this load. All writes in other threads that release the same atomic variable are visible in the current thread

memory_order_release: A store operation with this memory order performs the release operation: no reads or writes in the current thread can be reordered after this store. All writes in the current thread are visible in other threads that acquire the same atomic variable

This gives us four things to guarantee:

acquire ordering: "no reads or writes in the current thread can be reordered before this load"

release ordering: "no reads or writes in the current thread can be reordered after this store"

acquire-release synchronization:

"all writes in other threads that release the same atomic variable are visible in the current thread"

"all writes in the current thread are visible in other threads that acquire the same atomic variable"

Reviewing the guarantees:

Reads are not reordered with other reads.

Writes are not reordered with older reads.

Writes to memory are not reordered with other writes [..]

Individual processors use the same ordering principles as in a single-processor system.

This is sufficient to satisfy the ordering guarantees.

For acquire ordering, consider a read of the atomic has occurred: for that thread, clearly any later read or write migrating before would violate the first or second bullet points, respectively.

For release ordering, consider a write of the atomic has occurred: for that thread, clearly any prior reads or write migrating after would violate the second or third bullet points, respectively.

The only thing left is to ensure that if a thread reads a released store, it will see all the other loads the writer thread had produced up to that point. This is where the other multi-processor guarantee is needed.

Writes by a single processor are observed in the same order by all processors.

This is sufficient to satisfy acquire-release synchronization.

We've already established that when the release write occurs, all other writes prior to it will have also occurred. This bullet point then ensures that if another thread reads the released write, it will read all the writes the writer produced up to that point. (If it does not, then it would be observing that single processor's writes in a different order than the single processor, violating the bullet point.)


问:
How to maintain the state of CupertinoSegmentedControl for Internationalization?
I'm currently using internationalization from this link:
https://medium.com/flutter-community/flutter-internationalization-the-easy-way-using-provider-and-json-c47caa4212b2

But I change the buttons to CupertinoSegmentedControl instead.

The problem is the segment keep losing state when I leave the page.

I tried using AutomaticKeepAliveClientMixin but still didn't work.

Any answer will be appreciated!

答:
It's simple, you need to save/restore values, give shared_prefs a try

I'll do it using my plugin localize_and_translate

Here is a simple implementation for it

You get the active language code with method it will return language code : en for example

translator.currentLanguage();

2.You save to shared_prefs like following

```<code>import 'package:shared_preferences/shared_preferences.dart';

SharedPreferences prefs = await SharedPreferences.getInstance();
prefs.setString('code', translator.currentLanguage());
</code>```

3. Retrive like following inside your widget tree

```<code>prefs.getString('code') == 'en' ? // widget for true : // widget for false,
</code>```

Or  you can simply use my plugin directly without shared_prefs

```<code>translator.currentLanguage() == 'en' ? // widget for true : // widget for false,
</code>```

Body:
It's simple, you need to save/restore values, give shared_prefs a try

I'll do it using my plugin localize_and_translate

Here is a simple implementation for it

You get the active language code with method it will return language code : en for example

translator.currentLanguage();

2.You save to shared_prefs like following

import 'package:shared_preferences/shared_preferences.dart';

SharedPreferences prefs = await SharedPreferences.getInstance();
prefs.setString('code', translator.currentLanguage());

3. Retrive like following inside your widget tree

prefs.getString('code') == 'en' ? // widget for true : // widget for false,

Or  you can simply use my plugin directly without shared_prefs

translator.currentLanguage() == 'en' ? // widget for true : // widget for false,


问:
guess number in python
The program is such that the user selects a number in his mind and does not input it into the computer. (Number in range(1,99))

The program guesses and prints a number. randint(1,99)
The printed number creates three modes:
1-  is it larger than the number you have in mind when you type the letter ’s' into the program saying that the number in your mind is smaller than the number printed and the program has to guess and display another number (It should be noted that in this case, by typing ’s’ in the program, one has to guess a smaller number than his previous guess to finish the program sooner.)

2-or the printed number is smaller than the number you have in mind when you type the letter ‘l' into the program saying that the number in your mind is larger than the number printed and the program has to guess and display another number (It should be noted that in this case, by typing 'l', the program must guess a larger number than its predecessor in order to finish the program sooner.)

3=or is the printed number the same number that you had in mind and by typing the letter 'd' into the program you guess right and the program ends.

i try this

```<code>from random import randint
guess=randint(1,99)
print(guess)
my_answer=''
while my_answer != 'd':
    my_answer=input()
    if my_answer=="l":
        n=randint(guess,99)
        print(n)

    elif my_aswer=='s':
        m=randint(1,guess)
        print(m)
    else:
        print('done')
</code>```

But I don't know how that doesn't guess from the previous numbers again and make the range guess smaller.

答:
You need to change guess instead of using new variable n. You can also set the range of the guesses every time

```<code>low = 1
high = 99
guess = randint(low, high)
print(guess)
my_answer = ''
while my_answer != 'd':
    my_answer = input()
    if my_answer == "l":
        low = guess
        guess = randint(guess, high)
        print(guess)

    elif my_answer == 's':
        high = guess
        guess = randint(low, guess)
        print(guess)
    else:
        print('done')
</code>```

Example output

```<code>20
l
81
s
63
s
22
l
47
l
60
s
48
l
59
s
57
s
56
s
53
d
done
</code>```

Title: guess number in python

Body:
The program is such that the user selects a number in his mind and does not input it into the computer. (Number in range(1,99))

The program guesses and prints a number. randint(1,99)
The printed number creates three modes:
1-  is it larger than the number you have in mind when you type the letter ’s' into the program saying that the number in your mind is smaller than the number printed and the program has to guess and display another number (It should be noted that in this case, by typing ’s’ in the program, one has to guess a smaller number than his previous guess to finish the program sooner.)

2-or the printed number is smaller than the number you have in mind when you type the letter ‘l' into the program saying that the number in your mind is larger than the number printed and the program has to guess and display another number (It should be noted that in this case, by typing 'l', the program must guess a larger number than its predecessor in order to finish the program sooner.)

3=or is the printed number the same number that you had in mind and by typing the letter 'd' into the program you guess right and the program ends.

i try this

from random import randint
guess=randint(1,99)
print(guess)
my_answer=''
while my_answer != 'd':
    my_answer=input()
    if my_answer=="l":
        n=randint(guess,99)
        print(n)

    elif my_aswer=='s':
        m=randint(1,guess)
        print(m)
    else:
        print('done')

But I don't know how that doesn't guess from the previous numbers again and make the range guess smaller.

Body:
You need to change guess instead of using new variable n. You can also set the range of the guesses every time

low = 1
high = 99
guess = randint(low, high)
print(guess)
my_answer = ''
while my_answer != 'd':
    my_answer = input()
    if my_answer == "l":
        low = guess
        guess = randint(guess, high)
        print(guess)

    elif my_answer == 's':
        high = guess
        guess = randint(low, guess)
        print(guess)
    else:
        print('done')

Example output

20
l
81
s
63
s
22
l
47
l
60
s
48
l
59
s
57
s
56
s
53
d
done


问:
NameError: name 'run_once' is not defined in python
Python: 3.8.1

I wanted to run a method only once in my class. I have learned the following ways of achieving things and worked well.

```<code>def run_once():
    # Code for something you only want to execute once
    print("test")
    run_once.__code__ = (lambda: None).__code__
    return "Success"

print(run_once())
print(run_once())
print(run_once())
</code>```

Output:- --> Expected and Actual

```<code>test
Success
None
None
</code>```

Apparently, getting an error while trying to achieving the same via static method in a class.

```<code>class testing():

    @staticmethod
    def run_once(data):
        # Code for something you only want to execute once
        print(data)
        run_once("").__code__ = (lambda: None).__code__
        return "Success"

print(testing.run_once("test"))
</code>```

Trackback:-

```<code>Traceback (most recent call last):
  File "foo/test.py", line 11, in <module>
    print(testing.run_once("test"))
  File "foo/test.py", line 7, in run_once
    run_once("").__code__ = (lambda: None).__code__
NameError: name 'run_once' is not defined
test
</code>```

Could someone highlight where changes required to be made?

答:
The correct way to write these lines of code is:

```<code>class testing():

    @staticmethod
    def run_once(data):
        # Code for something you only want to execute once
        print(data)
        testing.run_once("").__code__ = (lambda: None).__code__
        return "Success"
print(testing.run_once("test"))
</code>```

Culprit line is run_once("").__code__ = (lambda: None).__code__ that is to be replaced with testing.run_once("").__code__ = (lambda: None).__code__. Howeveer it will also not solve the problem because now you are calling class function within the class that will cause exceeds the maxium limits error. Pleas try to improve your logic in this case. It is more about logical problem then syntax.

Correct logic and syntax will be:

```<code>class testing():
    @staticmethod
    def run_once(data):
        # Code for something you only want to execute once
        print(data)
        testing.run_once.__code__ = (lambda x: None).__code__
        return "Success"
print(testing.run_once("test"))
</code>```

Body:
Python: 3.8.1

I wanted to run a method only once in my class. I have learned the following ways of achieving things and worked well.

def run_once():
    # Code for something you only want to execute once
    print("test")
    run_once.__code__ = (lambda: None).__code__
    return "Success"

print(run_once())
print(run_once())
print(run_once())

Output:- --> Expected and Actual

test
Success
None
None

Apparently, getting an error while trying to achieving the same via static method in a class.

class testing():

    @staticmethod
    def run_once(data):
        # Code for something you only want to execute once
        print(data)
        run_once("").__code__ = (lambda: None).__code__
        return "Success"

print(testing.run_once("test"))

Trackback:-

Traceback (most recent call last):
  File "foo/test.py", line 11, in <module>
    print(testing.run_once("test"))
  File "foo/test.py", line 7, in run_once
    run_once("").__code__ = (lambda: None).__code__
NameError: name 'run_once' is not defined
test

Could someone highlight where changes required to be made?

Body:
The correct way to write these lines of code is:

class testing():

    @staticmethod
    def run_once(data):
        # Code for something you only want to execute once
        print(data)
        testing.run_once("").__code__ = (lambda: None).__code__
        return "Success"
print(testing.run_once("test"))

Culprit line is run_once("").__code__ = (lambda: None).__code__ that is to be replaced with testing.run_once("").__code__ = (lambda: None).__code__. Howeveer it will also not solve the problem because now you are calling class function within the class that will cause exceeds the maxium limits error. Pleas try to improve your logic in this case. It is more about logical problem then syntax.

Correct logic and syntax will be:

class testing():
    @staticmethod
    def run_once(data):
        # Code for something you only want to execute once
        print(data)
        testing.run_once.__code__ = (lambda x: None).__code__
        return "Success"
print(testing.run_once("test"))


问:
Display data after subscribe from firebase snapshot
I'm struggling with rxjs.. I would like to sort an array coming from my subscription.
But the sort never play..
SO first I tried to display userBirthdayDate from service but didn't work like expected.

this is my service

```<code> getAllUsers() {
    return new Promise((resolve, reject) => {
      firebase
        .database()
        .ref()
        .child('users')
        .on(
          'value',
          snapshot => {
            resolve(
              snapshot.forEach(childSnapshot => {
                this.usersBirthday = childSnapshot.val()
                  ? childSnapshot.val()
                  : [];
                this.emitBirthday();
              })
            );
          },
          error => {
            reject(error);
          }
        );
    });
  }
</code>```

my component.ts

```<code>export class WidgetBirthdayComponent implements OnInit {
  users: User[];
  usersBirthdayDate = [];
  usersSubscription: Subscription;

  constructor(private userService: UsersService) {}

  ngOnInit() {
    // this.usersSubscription = this.userService.birthdaySubject.subscribe(
    //   test => {
    //     this.usersBirthdayDate.push(test);
    //   }
    // );
    // this.userService.emitBirthday();
    // this.userService.getAllUsers();

    const myArray = [
      {
        name: "Joel",
        birthdayDate: "Wednesday, November 25, 1992"
      },
      {
        name: "Sarah",
        birthdayDate: "Thursday, April 16, 1992"
      },
      {
        name: "Beverly",
        birthdayDate: "Thursday, February 26, 1998"
      }
    ];

    myArray.sort(function compare(a, b) {
      const now = new Date();
      const dateA = new Date(a.birthdayDate);
      dateA.setFullYear(now.getFullYear());
      if (dateA.getTime() - now.getTime() < 0) {
        dateA.setFullYear(now.getFullYear() + 1);
      }
      const dateB = new Date(b.birthdayDate);
      dateA.setFullYear(new Date().getFullYear());
      dateA.setFullYear(now.getFullYear());
      if (dateB.getTime() - now.getTime() < 0) {
        dateB.setFullYear(now.getFullYear() + 1);
      }
      return dateA.getTime() - dateB.getTime();
    });
    console.log(myArray);
  }
</code>```

So I tried with strong data and my function sort is working well.. but I can"t use usersBirthdayDate[] on it.. PLease need help :)

答:
So this is my component.ts

I'm getting this on my console :

```<code>an array with the three elements inside my database

1: {birthdayDate: "Thursday, April 16, 1992", firstName: "Sarah", lastName: "Doe", photoUrl: "https://firebasestorage.googleapis.com/v0/b/dashbo…=media&token=9a2ee641-e5ee-4be5-827c-8369903a04ec"}
2: {birthdayDate: "Wednesday, November 25, 1992", firstName: "Thomas", lastName: "Loe", photoUrl: "https://firebasestorage.googleapis.com/v0/b/dashbo…=media&token=6736f24b-7c60-4722-9fad-9a8e73cc0e0a"}
3: {birthdayDate: "Thursday, February 26, 1998", firstName: "Sophie", lastName: "test", photoUrl: "https://firebasestorage.googleapis.com/v0/b/dashbo…=media&token=8ff30a9d-c644-4df6-8ecb-243121ccd7de"}
    length: 4
</code>```

but the function sort still doesn't work cause I have to get same array with Sophie first and sarah and Thomas. And when I tried with same data direct in component, the function is working well..

```<code>import { Component, OnInit } from '@angular/core';
import { UsersService } from '../../services/users.service';
import { User } from '../../models/user';
import { Subscription } from 'rxjs';

@Component({
  selector: 'app-widget-birthday',
  templateUrl: './widget-birthday.component.html',
  styleUrls: ['./widget-birthday.component.scss']
})
export class WidgetBirthdayComponent implements OnInit {
  users: User[];
  usersBirthdayDate = [];
  usersSubscription: Subscription;

  constructor(private userService: UsersService) {}

  ngOnInit() {
    this.usersSubscription = this.userService.birthdaySubject.subscribe(
      test => {
        this.usersBirthdayDate.push(test);
        this.usersBirthdayDate.sort(function compare(a, b) {
          const now = new Date();
          const dateA = new Date(a.birthdayDate);

          dateA.setFullYear(now.getFullYear());
          if (dateA.getTime() - now.getTime() < 0) {
            dateA.setFullYear(now.getFullYear() + 1);
          }
          const dateB = new Date(b.birthdayDate);
          dateA.setFullYear(new Date().getFullYear());
          dateA.setFullYear(now.getFullYear());
          if (dateB.getTime() - now.getTime() < 0) {
            dateB.setFullYear(now.getFullYear() + 1);
          }
          return dateA.getTime() - dateB.getTime();
        });
        console.log(this.usersBirthdayDate);
      }
    );
    this.userService.emitBirthday();
    this.userService.getAllUsers();

    // const myArray = [
    //   {
    //     name: 'Thomas',
    //     birthdayDate: 'Wednesday, November 25, 1992'
    //   },
    //   {
    //     name: 'Sarah',
    //     birthdayDate: 'Thursday, April 16, 1992'
    //   },
    //   {
    //     name: 'Sophie',
    //     birthdayDate: 'Thursday, February 26, 1998'
    //   }
    // ];
  }
}
</code>```

service.ts

```<code>import { Injectable } from '@angular/core';
import * as firebase from 'firebase';
import { User } from '../models/user';
import { Subject } from 'rxjs';

@Injectable({
  providedIn: 'root'
})
export class UsersService {
  users: User[] = [];
  usersSubject = new Subject<User[]>();
  birthdaySubject = new Subject<User[]>();
  usersBirthday: User[] = [];

  constructor() {}

  emitUsers() {
    this.usersSubject.next(this.users);
  }

  emitBirthday() {
    this.birthdaySubject.next(this.usersBirthday);
  }

  getAllUsers() {
    firebase
      .database()
      .ref()
      .child('users')
      .on('value', snapshot => {
        this.usersBirthday = snapshot.val()
          ? snapshot.val()
          : console.log('oro');
        this.emitBirthday();
      });
  }
}
</code>```

Body:
I'm struggling with rxjs.. I would like to sort an array coming from my subscription.
But the sort never play..
SO first I tried to display userBirthdayDate from service but didn't work like expected.

this is my service

 getAllUsers() {
    return new Promise((resolve, reject) => {
      firebase
        .database()
        .ref()
        .child('users')
        .on(
          'value',
          snapshot => {
            resolve(
              snapshot.forEach(childSnapshot => {
                this.usersBirthday = childSnapshot.val()
                  ? childSnapshot.val()
                  : [];
                this.emitBirthday();
              })
            );
          },
          error => {
            reject(error);
          }
        );
    });
  }

my component.ts

export class WidgetBirthdayComponent implements OnInit {
  users: User[];
  usersBirthdayDate = [];
  usersSubscription: Subscription;

  constructor(private userService: UsersService) {}

  ngOnInit() {
    // this.usersSubscription = this.userService.birthdaySubject.subscribe(
    //   test => {
    //     this.usersBirthdayDate.push(test);
    //   }
    // );
    // this.userService.emitBirthday();
    // this.userService.getAllUsers();

    const myArray = [
      {
        name: "Joel",
        birthdayDate: "Wednesday, November 25, 1992"
      },
      {
        name: "Sarah",
        birthdayDate: "Thursday, April 16, 1992"
      },
      {
        name: "Beverly",
        birthdayDate: "Thursday, February 26, 1998"
      }
    ];

    myArray.sort(function compare(a, b) {
      const now = new Date();
      const dateA = new Date(a.birthdayDate);
      dateA.setFullYear(now.getFullYear());
      if (dateA.getTime() - now.getTime() < 0) {
        dateA.setFullYear(now.getFullYear() + 1);
      }
      const dateB = new Date(b.birthdayDate);
      dateA.setFullYear(new Date().getFullYear());
      dateA.setFullYear(now.getFullYear());
      if (dateB.getTime() - now.getTime() < 0) {
        dateB.setFullYear(now.getFullYear() + 1);
      }
      return dateA.getTime() - dateB.getTime();
    });
    console.log(myArray);
  }

So I tried with strong data and my function sort is working well.. but I can"t use usersBirthdayDate[] on it.. PLease need help :)

Body:
So this is my component.ts

I'm getting this on my console :

an array with the three elements inside my database

1: {birthdayDate: "Thursday, April 16, 1992", firstName: "Sarah", lastName: "Doe", photoUrl: "https://firebasestorage.googleapis.com/v0/b/dashbo…=media&token=9a2ee641-e5ee-4be5-827c-8369903a04ec"}
2: {birthdayDate: "Wednesday, November 25, 1992", firstName: "Thomas", lastName: "Loe", photoUrl: "https://firebasestorage.googleapis.com/v0/b/dashbo…=media&token=6736f24b-7c60-4722-9fad-9a8e73cc0e0a"}
3: {birthdayDate: "Thursday, February 26, 1998", firstName: "Sophie", lastName: "test", photoUrl: "https://firebasestorage.googleapis.com/v0/b/dashbo…=media&token=8ff30a9d-c644-4df6-8ecb-243121ccd7de"}
    length: 4

but the function sort still doesn't work cause I have to get same array with Sophie first and sarah and Thomas. And when I tried with same data direct in component, the function is working well..

import { Component, OnInit } from '@angular/core';
import { UsersService } from '../../services/users.service';
import { User } from '../../models/user';
import { Subscription } from 'rxjs';

@Component({
  selector: 'app-widget-birthday',
  templateUrl: './widget-birthday.component.html',
  styleUrls: ['./widget-birthday.component.scss']
})
export class WidgetBirthdayComponent implements OnInit {
  users: User[];
  usersBirthdayDate = [];
  usersSubscription: Subscription;

  constructor(private userService: UsersService) {}

  ngOnInit() {
    this.usersSubscription = this.userService.birthdaySubject.subscribe(
      test => {
        this.usersBirthdayDate.push(test);
        this.usersBirthdayDate.sort(function compare(a, b) {
          const now = new Date();
          const dateA = new Date(a.birthdayDate);

          dateA.setFullYear(now.getFullYear());
          if (dateA.getTime() - now.getTime() < 0) {
            dateA.setFullYear(now.getFullYear() + 1);
          }
          const dateB = new Date(b.birthdayDate);
          dateA.setFullYear(new Date().getFullYear());
          dateA.setFullYear(now.getFullYear());
          if (dateB.getTime() - now.getTime() < 0) {
            dateB.setFullYear(now.getFullYear() + 1);
          }
          return dateA.getTime() - dateB.getTime();
        });
        console.log(this.usersBirthdayDate);
      }
    );
    this.userService.emitBirthday();
    this.userService.getAllUsers();

    // const myArray = [
    //   {
    //     name: 'Thomas',
    //     birthdayDate: 'Wednesday, November 25, 1992'
    //   },
    //   {
    //     name: 'Sarah',
    //     birthdayDate: 'Thursday, April 16, 1992'
    //   },
    //   {
    //     name: 'Sophie',
    //     birthdayDate: 'Thursday, February 26, 1998'
    //   }
    // ];
  }
}

service.ts

import { Injectable } from '@angular/core';
import * as firebase from 'firebase';
import { User } from '../models/user';
import { Subject } from 'rxjs';

@Injectable({
  providedIn: 'root'
})
export class UsersService {
  users: User[] = [];
  usersSubject = new Subject<User[]>();
  birthdaySubject = new Subject<User[]>();
  usersBirthday: User[] = [];

  constructor() {}

  emitUsers() {
    this.usersSubject.next(this.users);
  }

  emitBirthday() {
    this.birthdaySubject.next(this.usersBirthday);
  }

  getAllUsers() {
    firebase
      .database()
      .ref()
      .child('users')
      .on('value', snapshot => {
        this.usersBirthday = snapshot.val()
          ? snapshot.val()
          : console.log('oro');
        this.emitBirthday();
      });
  }
}