使用Javascript Fetch API异步排序提取的数据

以下名为runQuery was given to me by @Brad的javascript函数
它使用获取API从NodeJS服务器获取数据。
效果很好!它从服务器返回数据。

现在,我正在尝试对所有返回的数据进行排序。
以下代码运行无误,但返回最终的console.log命令查看时未排序的数据。
这是因为由于runQuery是异步的,所以sort函数在空数组上工作,因此不执行任何操作。然后,在runQuery有机会完成后,console.log将显示填充后的数组(未排序)。

只有将所有数据发送到浏览器后,才能帮助我理解如何对结果进行排序吗? 谢谢,约翰

P.S。此项目的所有工作代码都共享here

// Run the query defined in the textarea on the form.
runQuery(document.querySelector(".queryExpressionTextArea").value).then(function()
{
  // Sort the recordsArray which was populated after running the query.
  recordsArray.sort(function(a,b)
  {
    //Sort by email
    if (a.email > b.email) return -1;
    if (a.email < b.email) return 1;
    if (a.email === b.email) return 0;
  })

  console.log(recordsArray); 
}); 
async function runQuery(queryExpression)
  {   
    // Define a client function that calls for data from the server.
    const fetchPromise = fetch('api/aUsers' + queryExpression)
    .then
    (
      (res) => 
      {
        // Verify that we have some sort of 2xx response that we can use
        if (!res.ok) 
        {
          // throw res;         

          console.log("Error trying to load the list of users: ");        
        }

        // If no content,immediately resolve,don't try to parse JSON
        if (res.status === 204) 
        {
          return;
        }

        // Initialize variable to hold chunks of data as they come across.
        let textBuffer = '';

        // Process the stream.
        return res.body

        // Decode as UTF-8 Text
        .pipeThrough
        (
          new TextDecoderStream()
        )

        // Split on lines
        .pipeThrough
        (
          new TransformStream
          (
            {
              transform(chunk,controller) 
              {
                textBuffer += chunk;            

                // Split the string of records on the new line character and store the result in an array named lines.
                const lines = textBuffer.split('\n');

                // Cycle through all elements in the array except for the last one which is only holding a new line character.
                for (const line of lines.slice(0,-1))
                {
                  // Put the element from the array into the controller que.
                  controller.enqueue(line);
                } // End of: for (const line ...)

                // Put the last element from the array (the new line character) into the textBuffer but don't put it in the que.
                textBuffer = lines.slice(-1)[0];             
              },// End of: Transform(chunk,controller){do stuff}

              flush(controller) 
              {
                if (textBuffer) 
                {
                  controller.enqueue(textBuffer);
                } // End of: if (textBuffer)
              } // End of: flush(controller){do stuff}
            } // End of: parameters for new TransformStream
          ) // End of: call to constructor new TransformStream
        ) // End of: parameters for pipeThrough - Split on lines

        // Parse JSON objects
        .pipeThrough
        (
          new TransformStream
          (
            {
              transform(line,controller) 
              {
                if (line) 
                {
                  controller.enqueue
                  (
                    JSON.parse(line)
                  ); //End of: call to controller.enqueue function
                } // End of: if (line)
              } // End of: transform function
            } // End of: parameter object for new TransformStream
          ) // End of: new TransformStream parameters
        ); // End of: parameters for .pipeThrough - Parse JSON objects
      } // End of: .then callback function instruction for fetch
    ); // End of: .then callback parameters for fetch


    // Call to function which asks server for data.
    const res = await fetchPromise;

    const reader = res.getReader();

    function read() 
    {
      reader.read()
      .then
      (
        ({value,done}) => 
        {
          if (value) 
          {
            // Your record object (value) will be here.
            // This is a key/value pair for each field in the record.   
            //*************************
            // This array has global scope.
            // I want to sort this array only after all the data has been returned.  
            // In other words - only after this asynchronous function has finished running.   
            recordsArray.push(value);
            //*************************

            // If I were to uncomment the sort function in this position then
            // we will see the records sorted correctly in the final console.log.
            // I don't want to do this because then the sort function will
            // run every time a record is returned rather than one time after
            // all the records have been retrieved.

            //recordsArray.sort(function(a,b)
            //{
            //  //Sort by email
            //  if (a.email > b.email) return -1;
            //  if (a.email < b.email) return 1;
            //  if (a.email === b.email) return 0;
            //})


          } // End of: if(value){do stuff}

          if (done) {return;}

          read();

        } // End of: the actual anonymous callback arrow function.
      ); // End of: .then callback after read function completes.
    } // End of: function definition: function read(){do stuff}

    // Call the "read" function defined above when the submit query button is pressed.
    read()

  }; // End of: async function runQuery(queryExpression)
hustsky123 回答:使用Javascript Fetch API异步排序提取的数据

好像您没有在寻找任何流媒体。只是写

FinishBundle

然后

async function runQuery(queryExpression) {
    const res = await fetch('api/aUsers' + queryExpression);
    // Verify that we have some sort of 2xx response that we can use
    if (!res.ok) {
        console.log("Error trying to load the list of users: ");
        throw res;
    }
    // If no content,immediately resolve,don't try to parse JSON
    if (res.status === 204) {
        return [];
    }
    const content = await res.text();
    const lines = content.split("\n");
    return lines.map(line => JSON.parse(line));
}
,

我在the webpage found here的帮助下使用了此解决方案。
但是,我从@Bergi中选择答案作为解决方案,因为代码更短,更优雅,并且因为Bergi提出了这样的观点,即等待提取完成将减少使用流的好处。

此功能的所有工作代码都可以在以下功能中找到at this link
app.loadUsersListPage =异步功能(){做事}

请注意上面的关键字async-这对于使这项工作很有必要。

该操作以loadUsersListPage的子函数onClickEventBehaviorOfSubmitQueryButton开始。

对该功能进行了以下更改,以使所有功能均起作用。请注意,它与原始问题中的代码有何不同。

    // Run the query defined in the textarea on the form.
    let recordsArray = await runQuery(document.querySelector(".queryExpressionTextArea").value)

    // Sort the recordsArray which was populated after running the query.
    recordsArray.sort(function(a,b)
    {
      //Sort by email
      if (a.email > b.email) return -1;
      if (a.email < b.email) return 1;
      if (a.email === b.email) return 0;
    })

    console.log(recordsArray);

上面的代码调用下面的代码,下面的代码也进行了更改以使其全部正常工作。
注意在整个函数中使用关键字async和await。
另请注意,在函数底部已更改了代码,以便直到从服务器接收到所有数据后,数据才返回到排序函数。

  async function runQuery(queryExpression)
  {
    // Define a client function that calls for data from the server.
    //                    !!!
    const fetchPromise = await fetch('api/aUsers' + queryExpression)
    .then
    (
      (res) => 
      {
        // Verify that we have some sort of 2xx response that we can use
        if (!res.ok) 
        {
          // throw res;

          // Show the createCheck CTA
          document.getElementById("createNewRecordCTA").style.display = 'block';
          document.getElementById("createNewRecordCTA2").style.display = 'block';
          document.getElementById("createNewRecordCTA3").style.display = 'block';          

          console.log("Error trying to load the list of users: ");        
        }

        // If no content,don't try to parse JSON
        if (res.status === 204) 
        {
          return;
        }

        // Initialize variable to hold chunks of data as they come across.
        let textBuffer = '';

        // Process the stream.
        return res.body

        // Decode as UTF-8 Text
        .pipeThrough
        (
          new TextDecoderStream()
        )

        // Split on lines
        .pipeThrough
        (
          new TransformStream
          (
            {
              transform(chunk,controller) 
              {
                textBuffer += chunk;            

                // Split the string of records on the new line character and store the result in an array named lines.
                const lines = textBuffer.split('\n');

                // Cycle through all elements in the array except for the last one which is only holding a new line character.
                for (const line of lines.slice(0,-1))
                {
                  // Put the element from the array into the controller que.
                  controller.enqueue(line);
                } // End of: for (const line ...)

                // Put the last element from the array (the new line character) into the textBuffer but don't put it in the que.
                textBuffer = lines.slice(-1)[0];             
              },// End of: Transform(chunk,controller){do stuff}

              flush(controller) 
              {
                if (textBuffer) 
                {
                  controller.enqueue(textBuffer);
                } // End of: if (textBuffer)
              } // End of: flush(controller){do stuff}
            } // End of: parameters for new TransformStream
          ) // End of: call to constructor new TransformStream
        ) // End of: parameters for pipeThrough - Split on lines

        // Parse JSON objects
        .pipeThrough
        (
          new TransformStream
          (
            {
              transform(line,controller) 
              {
                if (line) 
                {
                  controller.enqueue
                  (
                    JSON.parse(line)
                  ); //End of: call to controller.enqueue function
                } // End of: if (line)
              } // End of: transform function
            } // End of: parameter object for new TransformStream
          ) // End of: new TransformStream parameters
        ); // End of: parameters for .pipeThrough - Parse JSON objects
      } // End of: .then callback function instruction for fetch
    ); // End of: .then callback parameters for fetch

    // Below the code has been changed so that data is not returned until the entire fetch has been completed.
    // Call to function which asks server for data.
    const res = await fetchPromise;

    const reader = res.getReader();

    let result = await reader.read();
    let fetchedArray = [];

    while (!result.done) {
      const value = result.value;
      fetchedArray.push(value);
      // get the next result
      result = await reader.read();
    }

    return fetchedArray;

  }; // End of: async function runQuery(queryExpression)

感谢大家帮助我完成这项工作。
显然,我需要学习异步/等待并承诺是否希望实现自己的目标。

本文链接:https://www.f2er.com/3087877.html

大家都在问