新的Promise()与(async()=> {})()

时间:2019-07-27 12:04:14

标签: javascript promise async-await iife

第1块:

const promise = new Promise((resolve) => {
  setTimeout(resolve, 100);
});

第2块:

const promise = (async () => {
  await new Promise(resolve => {
    setTimeout(resolve, 100);
  });
})();

以上两个块是否等效?有什么值得注意的区别吗?

我知道这是一个非常人为的示例,此处的第2块没有太多用途。但是我遇到的一种情况是我想创建并存储对Promise的引用,但是Promise执行程序功能需要使用wait来获取一些数据。但是声明new Promise(async (resolve) => {});被认为是反模式。在这种情况下,第2块更好吗?

更新:提供有关我要执行的操作的更具体示例:

  export async function getData(request) {
    // De-dupe fetches for the same request and return existing promise.
    if (map.has(JSON.stringify(request))) {
      return map.get(JSON.stringify(request));
    }

    const thePromise = (async () => {
      const [foo, bar] = Promise.all(await getFoo(), await getBar());

      const theData = await getTheData(foo, bar);

      return theData.some.thing ? 'a' : 'b';
    })();

    map.put(JSON.stringify(request), thePromise);
    return thePromise;
  }

3 个答案:

答案 0 :(得分:1)

在第二种方法中,您可以使用trycatch块,如下所示:

const promise = (async () => {
try {
  await new Promise(resolve => {
    setTimeout(resolve, 100);
  });
} catch(err => {
// handle error here
})
})();

答案 1 :(得分:0)

  

提供我正在尝试做的更具体的例子

您对async立即执行的函数表达式的使用在这里完全可以,它没有任何问题。当然,您可以使用.then()链来编写相同的内容,但这并不完全一样。

一些小改进:

export function getData(request) {
//    ^ no need for `async` when you return a promise anyway
  const requestKey = JSON.stringify(request); // compute only once
  if (map.has(requestKey)) {
    return map.get(requestKey);
  }
  const thePromise = (async () => {
    const [foo, bar] = await Promise.all([getFoo(), getBar()]);
//                     ^^^^^ had `await` keywords in the wrong places
    const theData = await getTheData(foo, bar);
    return theData.some.thing ? 'a' : 'b';
  })();
  map.set(requestKey, thePromise);
  return thePromise;
}

答案 2 :(得分:-1)

不确定这是否是您说的意思

  

但是promise executor函数需要使用await来获取一些数据

但是听起来您正在处理一个需要“等待”的promise中的异步调用,然后resolve处理作为结果返回的数据。

例如,

编辑:正如 @Bergi 在以下评论中指出的那样,您可能不应该这样做(将一个承诺包装在另一个承诺中):

// Assuming you're making an API with `axios` to grab some data
const promise = new Promise((resolve, reject) => {
  axios.get('www.example.com/api', {...})
    .then(result => {
      resolve(result)
    })
    .catch(error => {
      reject(error)
    })
})
const callback = (data) => {
  console.log('data', data)
}

// `callback` will get called when the `axios.get` "finishes" (resolves) 
// with some data after it's done fetching, no need to `await` here

promise.then(callback)

相反,如果需要,您可以承诺链接:

// using the same example from above
const handleResponse = (result) => {
  // handle response
}
const handleError = (error) => {
  // handle error
}

axios.get('www.example.com/api', {...})
  .then(handleResponse)
  .then(doSomethingElse)
  .catch(handleError)

// or, if you need to make multiple asynchronous calls use `Promise.all`
const handleResponses = (response) => {
  const [users, books] = response
  // do the rest
}

Promise.all([
  axios.get('www.example.com/api/users'),
  axios.get('www.example.com/api/books')
])
  .then(handleAPIResponses)
  .then(doSomethingElse)
  .catch(handleError)

类似地,如果您要处理“错误优先”的回调模式

// `fs.readFile` with Node.js
const promise = new Promise((resolve, reject) => {
  fs.readFile('...', (err, data) => {
    if (err) {
      reject(err)
      return
    }
    resolve(data)
  })
})
const callback = (data) => {
  console.log('data', data)
}

// again, `callback` will get called when reading a file is done
// and you get the result back

promise.then(callback)

如果您需要在promise内部进行多个调用,然后使用最终值进行解析,则可以执行以下操作:

async function promise() {
  try {
    // assuming API.getUserIds() returns a promise
    const userIds = await API.getUserIds(...)
    const users = await API.getUsers(userIds)

    return users
  } catch (err) {
    // ...
  }
}
const callback = (data) => {
  console.log('data', data)
}

// again, `callback` will get called when both API requests 
// resolve with some values and when the above function returns `users`

promise().then(callback)

就我个人而言,我会远离#2,无论您要尝试使用哪种模式(取决于您的情况),都可以轻松选择上面的示例之一来完成该操作。