在数据处理之前返回的函数

Function returning before data is processes

我认为 for 循环在 Javascript 中阻塞,但此函数在 for 循环完成之前返回一个空数组。这个问题的答案是设置一个仅使用 for 循环作为承诺的新函数吗?如果是这样的话,那看起来像什么,promise 的语法真的让我感到困惑。

async function retrieve_s3_file(to_do_list, guid){
  var data_list = [];

  for (let i = 0; i < to_do_list.length; i++)
  {
    element = to_do_list[i];
    console.log("\n\nOutgoing request /jobs/list?guid=" + guid + "&file=" + element);
    axios.get(job_queue_url + "?guid=" + guid + "&file=" + element)
    .then(function (res){
      data_list.push(res.data);
      console.log("Inside Loop: " + JSON.stringify(data_list));
    })
    .catch(function (error){
      console.log(error);
    });
  }

  console.log("Data List: " + JSON.stringify(data_list));
  return JSON.stringify(data_list);
}

Javascript 是单线程的,因此循环通常是阻塞的,但在这种情况下,您的承诺会将其新任务放在堆栈的末尾。 如果您使用 await ,则不应创建新任务,并且它应该按照您的意愿运行。但是你正在制作它 sycronus 所以它会比以前慢一点。

async function retrieve_s3_file(to_do_list, guid){
  var data_list = [];

  for (let i = 0; i < to_do_list.length; i++)
  {
    element = to_do_list[i];
    console.log("\n\nOutgoing request /jobs/list?guid=" + guid + "&file=" + element);
    await axios.get(job_queue_url + "?guid=" + guid + "&file=" + element)
    .then(function (res){
      data_list.push(res.data);
      console.log("Inside Loop: " + JSON.stringify(data_list));
    })
    .catch(function (error){
      console.log(error);
    });
  }

  console.log("Data List: " + JSON.stringify(data_list));
  return JSON.stringify(data_list);
}

axios.get是一个承诺。在 javascript 中,promise 是非阻塞的,这意味着 then 函数中给出的回调将 运行 一旦 promise 解决。但是 promise 不会阻塞线程。

下面的例子反映了题目的问题。控制台打印 start end 然后 ok。因为 customPromise 是一个承诺,并且在没有 await 的情况下调用它,调用者不会 等待 该承诺完成,因此调用者将继续执行并打印 end。请注意,此承诺会立即得到解决,但回调 res => console.log(res) 将在最后执行,因为它是一个承诺回调。

const customPromise = new Promise((resolve, reject)=>{resolve('ok')})


function nonBLockingExample (){
  console.log('start');
  customPromise.then(res => console.log(res));
  console.log('end');
}

nonBLockingExample();

下面是所需输出的示例。调用者 等待 以等待 customPromise 解析,因为 customPromise 是使用 await 关键字调用的。

const nonBlockingPromise = new Promise((resolve, reject)=>{resolve('ok')})

async function bLockingExample (){
  console.log('start');
  await nonBlockingPromise.then(res => console.log(res));
  console.log('end');
}

bLockingExample();

因此,要将修复应用到您的代码,只需等待 axios.get。 (await axios.get(.....)

如果您使用异步操作,它不会阻塞。

如果你想让 Axios 在请求结束之前等待,你可以使用 await 关键字,否则使用 promises。 收集它们并使用 Promise.all 当所有请求都得到解决时,您可以将所有响应作为数组获取。

async function retrieve_s3_file(to_do_list, guid) {
  const requests = [];
  for (const file of to_do_list) {
    const params = new URLSearchParams({ guid, file });
    const request = axios.get(`${job_queue_url}?${params.toString()}`);
    requests.push(request.then((response) => response.data));
  }

  return Promise.all(requests).then(JSON.stringify);
}