Javascript(Chrome 扩展):如何使用提取和强制代码正确执行多个 API 调用以等待调用完成?

Javascript (Chrome Extension): How to correctly execute multiple API calls using fetch and force code to wait for the calls to finish?

我正在尝试使用 gmail api 创建一个 chrome 扩展。我正在使用 api 调用来获取某些信息,然后遍历结果并针对每个结果执行另一个 api 调用。这些调用完成后,其余代码将 运行。我现在面临的问题是其余代码在提取返回信息之前正在执行。

以下是不起作用的功能。我在代码中添加了 4 个标志以更好地说明问题。正确的行为应该输出标志 1,然后循环 2,然后循环 3,然后 4。但是,实际行为输出标志 1,然后循环 2,然后 4,然后循环标志 3。

我的一个理论是,原因是我在 .then() 内部使用了提取。如果这是问题所在,我该如何解决?或者它与获取异步有什么关系?任何建议或有用的链接都将不胜感激。

非常感谢!

  let senderList = new Array();
  let init = {
    method: 'GET',
    async: true,
    headers: {
      Authorization: 'Bearer ' + token,
      'Content-Type': 'application/json'
    },
    'contentType': 'json'
  };
  fetch(
    'https://gmail.googleapis.com/gmail/v1/users/me/messages?key=ABCDEFGHIJKLMNOPQRSTUVWXYZ1234',
    init)
    .then((response) => response.json())
    .then(function(data) {
      console.log("Flag 1")
      let messageResponse = data.messages; //Array of Message Objects
      for (let i = 0; i < messageResponse.length; i++) {
        console.log("Flag 2")
        fetch(
          'https://gmail.googleapis.com/gmail/v1/users/me/messages/' + messageResponse[i].id +
              '?key=ABCDEFGHIJKLMNOPQRSTUVWXYZ1234',
          init)
          .then((response) => response.json())
          .then(function(message) {
            let headers = message.payload.headers;
            console.log("Flag 3")
            for (let i = 0; i < headers.length; i++) {
              if (headers[i].name == 'From'){
                senderList.push(headers[i].value);
              }              
            }               
          });          
      }
    }).then(function() {
      console.log("Flag 4")
      onSuccess(senderList);
    });        
}

将 async/await 语法与 Promise.all 一起使用,当所有承诺都得到满足时解析:

run();

async function run() {
  const list = await getSenderList();
  console.log(list, list.errors);
}

async function getSenderList() {
  const API_URL = 'https://gmail.googleapis.com/gmail/v1/users/me/messages/';
  const API_KEY = '?key=...';
  const INIT = {method: 'GET', /* ... etc. */ };
  const data = await fetchJson(API_URL + API_KEY);
  const senderList = [];
  senderList.errors = {};
  await Promise.all(data.messages.map(async msg => {
    const msgData = await fetchJson(API_URL + msg.id + API_KEY, INIT);
    if (msgData instanceof Error) {
      senderList.errors[msg.id] = msgData;
      return;
    }
    const headers = msgData.payload.headers;
    for (const h of headers) {
      if (h.name === 'From') {
        senderList.push(h.value);
      }
    }
  }));
  return senderList;
}

function fetchJson(url, init) {
  return fetch(url, init).then(r => r.json()).catch(err => err);
}