Как реорганизовать асинхронную функцию обещания в не асинхронную, чтобы избежать анти-паттерна - PullRequest
0 голосов
/ 17 марта 2019

Я пытаюсь выполнить рефакторинг кода, где я использую анти-шаблон, но все еще не понимаю, как именно рефакторинг что-то вроде этого: У меня есть функция, которая работает сейчас так:

export async function submit(data) {
  return new Promise(async function(resolve, reject) {
    ...
    let list = await getList();
    ...
    for (let i = 0; i < list.length; i++) {
       let data = await getData(list[i]);
    }
    ...
    for (let i = 0; i < list.length; i++) {
       let response = await uploadFile(list[i]);
    }

И я называю эту функцию как:

let response = await submit(data);

Я понимаю, что асинхронная функция в новом Promise - проблема, но как ее исправить?

export async function submit(data) {
  return new Promise(async function(resolve, reject) {
  let files = getFiles();

      let prepareUrlsResponse = await prepareUrls(paths);
      if (prepareUrlsResponse.error === true) {
        resolve( { success: false });
      } else {
        let blobs = [];
        for (let i = 0; i < prepareUrlsResponse.data.length; i++) {
          let fileData = await RNFetchBlob.fs.stat(filePath);
          blobs.push(fileData);
        }

        for (let i = 0; i < blobs.length; i++) {
          let item = blobs[i];

          let response = await uploadFile(
            item.url,
            item.blob
          );

          if (response && response.uploadSuccess === false) {
            resolve( { success: false });
            break;
          }
        }
      }


    api.post(
      endpoint,
      data,
      response => {
        if (response.ok) {
          resolve( { success: true, response: response });
        } else {
          resolve( { success: false });
        }
      }
    );
  });
}

1 Ответ

3 голосов
/ 17 марта 2019

Просто бросьте черту полностью.Ваш submit уже является async function, вы можете использовать await непосредственно в нем.Нет необходимости создавать new Promise вокруг всего этого, вам нужно его только для promisfy вызова api.post.Вы должны выделить это в отдельную функцию, возвращающую обещание, и использовать await в нем, как и в других вызываемых вами функциях.

function postData(url, data) {
  return new Promise(function(resolve, reject) {
//                   ^^^^^^^^ no `async` here!
    api.post(url, data, resolve);
  });
}

export async function submit(data) {
  let files = getFiles();
  let prepareUrlsResponse = await prepareUrls(paths);
  if (prepareUrlsResponse.error === true) {
    return { success: false };
  } else {
    let blobs = [];
    for (let i = 0; i < prepareUrlsResponse.data.length; i++) {
      let fileData = await RNFetchBlob.fs.stat(filePath);
      blobs.push(fileData);
    }

    for (let i = 0; i < blobs.length; i++) {
      let item = blobs[i];
      let response = await uploadFile(
        item.url,
        item.blob
      );

      if (response && response.uploadSuccess === false) {
        return { success: false };
      }
    }
  }

  const response = await postData(endpoint, data);
  if (response.ok) {
    return { success: true, response: response });
  } else {
    return { success: false };
  }
}

Конечно, вы можетевставьте вызов postData и используйте const response = await new Promise(…);, но вы должны оборачивать только части обратного вызова, а не всю логику.

...