javascript - 使用 Javascript Fetch API 对异步获取的数据进行排序

标签 javascript sorting asynchronous async-await fetch-api

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

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

有人可以帮我理解如何在所有数据发送到浏览器后对结果进行排序吗? 谢谢,约翰

附注该项目的所有工作代码均已共享 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)

最佳答案

看起来您并没有在寻找任何流媒体。就这么写

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));
}

然后

const recordsArray = await runQuery(document.querySelector(".queryExpressionTextArea").value);
recordsArray.sort(function(a, b) {
    return (a.email < b.email) - (a.email > b.email);
})
console.log(recordsArray); 

关于javascript - 使用 Javascript Fetch API 对异步获取的数据进行排序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58897018/

相关文章:

javascript - 如何在悬停时使图像在 div 中向上移动

javascript - jquery .is (':disabled' ) 不工作

python - 根据值对字典进行排序

java - 来自 servlet 的 Java 异步处理

.net - 为什么 SynchronizationContext 不能正常工作?

javascript - 如何在 Protractor 中使用异步等待?

javascript - 传递带有设置参数的函数

javascript - Angular 2 快速入门演示不起作用

c# - 收藏修改项目

c - 字符串冒泡排序