Web-App for to determine gender, age, emotions of a person (shown on an image) I have made an app using Microsoft's Face API: Face API JavaScript Quick Start

It shall analyze an image, showing a person's portrait, concerning the gender of the person, her/his age and emotions. 

One pastes the URL of an image into the text-box. Then clicks the button. 

The results are then listed below the image.

Caution! I'm using a free, temporary key in there. The app might stop working some time after my post.



(function(window) {
  var headersObject = new Headers();
  var photo = document.getElementById('analyzedPhoto');
  var attributesList = document.getElementById('attributes');

  headersObject.append('Ocp-Apim-Subscription-Key', '32fee7696d9545bdab41fd09ffb00034');
  headersObject.append('Content-Type', 'application/json');

  document
    .getElementById('analyse')
    .addEventListener('click', () =&gt; {
      var imgUrl = document.getElementById('imageUrl').value;

      var initObject = {
        headers: headersObject,
        method: 'post',
        body: '{"url": "' + imgUrl + '"}'
      }

      photo.src = imgUrl;

      fetch('https://westcentralus.api.cognitive.microsoft.com/face/v1.0/detect?returnFaceId=true&amp;returnFaceAttributes=emotion,age,gender', initObject)
        .then((response) =&gt; {
          !response.ok &amp;&amp;
            Promise.reject(new Error('The request of analysis data has failed.'));

          return response.json();
        })
        .then((json) =&gt; {
          let facesAttributes =
            Object.assign({},
              json[0].faceAttributes,
              json[0].faceAttributes.emotion);
          let listItems = [];
          // Otherwise emotion-properties AND emotion-object self are contained in attributes-object.
          delete facesAttributes.emotion;

          for (let key in facesAttributes) {
            listItems.push('&lt;li class="list-item"&gt;&lt;span class="list-item-key"&gt;' +
              (key.slice(0, 1).toUpperCase()) +
              (key.slice(1)) + '&lt;/span&gt;: ' + facesAttributes[key] +
              '&lt;/li&gt;');
          }

          attributesList.innerHTML = listItems.join('');
        })
        .catch((error) =&gt; {
          console.dir(error);
          attributesList.innerHTML = 'Have you entered a valid image URL?';
        });
    });
})(window);
html {
  overflow-y: scroll;
  background-color: rgba(245, 245, 245, 1.0);
  font-family: "Trebuchet MS", "Lucida Grande", "Lucida Sans Unicode", "Lucida Sans", Tahoma, sans-serif;
}

.main-wrap {
  margin: 0 auto 30px;
  max-width: 800px;
}

#imageUrl {
  display: inline-block;
  width: 100%;
  max-width: 780px;
}

#analyzedPhoto {
  margin: 15px;
  border-radius: 3px;
  max-width: 100%;
  height: auto;
}

#attributes {
  list-style: none;
  padding-left: 0;
}

#attributes .list-item {
  margin-bottom: 10px;
}

.list-item-key {
  font-weight: 900;
  color: rgba(20, 20, 20, 1.0);
}
&lt;div class="main-wrap"&gt;
  &lt;h1&gt;Enter Image URL&lt;/h1&gt;

  &lt;section&gt;
    &lt;p&gt;
      &lt;input type="text" value="https://upload.wikimedia.org/wikipedia/commons/thumb/5/56/Tesla3.jpg/220px-Tesla3.jpg" id="imageUrl" /&gt;
    &lt;/p&gt;
    &lt;button id="analyse"&gt;Analyse&lt;/button&gt;
  &lt;/section&gt;

  &lt;section&gt;
    &lt;img src="" id="analyzedPhoto" alt="Photo to analyze" /&gt;
  &lt;/section&gt;

  &lt;section&gt;
    &lt;h2&gt;Attributes&lt;/h2&gt;
    &lt;ul id="attributes"&gt;&lt;/ul&gt;
  &lt;/section&gt;
&lt;/div&gt;




Is my usage of the fetch-API and Promises correct and done in a good way?

These concepts are fairly new to me.

Moreover: I had a bit of hassle merging the two objects into one. Please see my comment within the code.

Is there a better solution than deleting the unnecessary sub-object?
Addressing Your Questions

Is my usage of fetch-API and Promises correct and done in a good way?

Yes it seems fine. The Fetch API is supported by all major browsers but not IE1 but some argue that it doesn't really have a simple way to cancel requests. If there arises a need to abort requests, then other libraries like SuperAgent or reqwest could be used.

Is there are better solution then deleting the unnecessary sub-object?

Obviously there are other ways to handle setting the values within the emotion property on faceAttributes, but those might likely require more lines. One could also conditionally display list items (e.g. add if (typeof facesAttributes[key] !== &quot;object&quot;) { before the line that pushes strings into listItems). If there was a way to filter with a callback when calling Object.extend() that would be an advantage here but unfortunately it doesn't appear that is the case.
Other review points
Feedback
The code looks quite succint. There are two DOM lookups at the start but then one DOM lookup in the click handler so that could be cached in a variable.
Suggestions
var vs let/const
Perhaps you have already learned more about let and const since posting this question but many es-6 developers would prefer using const for values that don't change (e.g. imgUrl, initObject, etc.)
Template
One could also utilize a script template to display the list items, though that may not be desirable here.
Invalid HTML when Error occurs
This line in the promise catch:

attributesList.innerHTML = 'Have you entered a valid image URL?';


Sets the inner HTML of the unordered list tag to a text string. That is technically unpermitted content for an unordered list. Perhaps a better solution would be to have a separate element for the error message.
P.S.
Here is the output from that AJAX call using that image of Tesla, so you could fake it now that the key is invalid:


const output = [{"faceId":"950c26ae-70f0-4365-8279-fcd987f56e70","faceRectangle":{"top":75,"left":32,"width":117,"height":117},"faceAttributes":{"gender":"male","age":37.0,"emotion":{"anger":0.0,"contempt":0.0,"disgust":0.0,"fear":0.0,"happiness":0.007,"neutral":0.992,"sadness":0.0,"surprise":0.0}}}];
const p1 = new Promise(function(resolve, reject) {
  setTimeout(resolve, 100, output);
  });
p1.then(console.log);