title: unwrapping nested promises in JS
body: <p>Relatively simple task:</p>
  <p>Make repeated REST requests for data and concatenate parts of each response into a single list for processing. I'm struggling to wrap my head around the js async model and wondering if this just isn't the appropriate task? Bottom line is -- what is the idiomatic way of dealing with a situation like below?</p>
  <pre><code>const https = require('https');
  
  function post(body, path, token = null) {
      const data = JSON.stringify(body);
      const headers = {
          accept: 'application/json',
          'Content-Type': 'application/json',
          'Content-Length': data.length,
          'Authorization': token,
      }
      const options = {
          hostname: 'api.sensorpush.com',
          port: 443,
          path: path,
          method: 'POST',
          headers: headers,
      }
  
      return new Promise((resolve, reject) =&gt; {
          let body = Buffer.alloc(0)
          const req = https.request(options, (res) =&gt; {
              res.on('data', (d) =&gt; {
                  body = Buffer.concat([body, d])
              })
              res.on('end', () =&gt; {
                  if (res.statusCode !== 200) {
                      reject(new Error(`Got status code ${res.statusCode}`))
                  }
                  try {
                      return resolve(JSON.parse(body.toString()))
                  } catch (e) {
                      reject(e)
                  }
              })
          })
          req.on('error', (err) =&gt; reject(err))
          req.write(data)
          req.end()
      })
  }
  
  async function get_data(time) {
      const auth_body = {
          email: usrname,
          password: pw,
      }
      const auth_path = '/api/v1/oauth/authorize'
      let { authorization } = await post(auth_body, auth_path)
      const tok_body = {
          &quot;authorization&quot;: authorization
      }
      const tok_path = '/api/v1/oauth/accesstoken'
      let { accesstoken } = await post(tok_body, tok_path)
  
      endTime = new Date(time)
      startTime = new Date(time.setDate(time.getDate() - 1))
  
      let s1 = []
      let s2 = []
      while (startTime &lt; endTime) {
          console.log(startTime)
          data_body = {
              &quot;startTime&quot;: startTime.toISOString(),
          }
          data_path = '/api/v1/samples'
          data = await post(data_body, data_path, accesstoken)
          startTime = new Date(data['last_time'])
          s1 = s1.concat(data['sensors']['305349.3638533352933283797'])
          s2 = s2.concat(data['sensors']['305349.3638533352933283797'])
      }
      return s1, s2
  }
  </code></pre>
  <p>When I call <code>get_data()</code> I'm returned something like this:</p>
  <pre><code>&gt; data
  Promise {
    {
      last_time: '2021-02-08T06:25:55.000Z',
      sensors: {
        'SENSORID': [Array],
        'SENSORID': [Array]
      },
      truncated: false,
      status: 'OK',
      total_samples: 25,
      total_sensors: 2
    }
  }
  </code></pre>
  <p>But I don't know how to actually USE the values here outside of executing some really long and verbose chain of <code>then(...)</code>'s. If I say <code>data.then((o) =&gt; o['sensors']</code> now I have</p>
  <pre><code>&gt; s
  Promise {
    {
      'SENSORID': [
        [Object], [Object],
        [Object], [Object],
        [Object], [Object],
        [Object], [Object],
        [Object], [Object]
      ],
      'SENSORID': [
        [Object], [Object],
        [Object], [Object],
        [Object], [Object],
        [Object], [Object],
        [Object], [Object],
        [Object], [Object],
        [Object], [Object],
        [Object]
      ]
    }
  }
  </code></pre>
  <p>And it goes on and on...</p>