【问题标题】:How to refactor async promise function to non async to avoid anti pattern如何将异步承诺功能重构为非异步以避免反模式
【发布时间】:2019-03-18 01:34:21
【问题描述】:

我正在尝试重构使用反模式的代码,但仍然不明白如何重构这样的东西: 我现在有一个像这样工作的函数:

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

我了解 new 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 });
        }
      }
    );
  });
}

【问题讨论】:

  • 请贴出函数的完整代码,最重要的是你调用resolvereject的部分。
  • 我更新了问题。我删除了一些不相关的部分,但保留了我解决的所有地方。我试图删除new Promise(),但是当return 我得到undefined

标签: javascript promise async-await es6-promise


【解决方案1】:

完全放下这条线。您的submit 已经是async function,您可以直接在其中使用await。没有必要围绕整个事情创建一个new Promise,你只需要promisfyapi.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(…);,但您应该只包装回调部分而不是整个逻辑。

【讨论】:

  • 并添加 try catch 块 :)
  • 嗯,好的,谢谢return instead of calling resolve(), throw instead of calling reject() 的评论:) 我认为为了await 我需要有new Promise 内部函数。所以当我调用这应该是try{let res = await submit(data)} catch(err){} 等错误它会在这里捕获它?
  • @CodeManiac 不是吗?如果你没有捕捉到异常,promise 就会被拒绝,正如人们所希望的那样。
  • @1110 不,您需要async 才能使用awaitnew Promise 与此无关。是的,你会像以前一样称呼它。有关更多详细信息,请编辑您的问题,以便我可以扩展我的答案。
  • 我更新了问题,我在那里做错了吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-05-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-01-30
  • 1970-01-01
相关资源
最近更新 更多