【问题标题】:Convert async/await style to traditional .then style将 async/await 样式转换为传统的 .then 样式
【发布时间】:2018-11-24 12:33:46
【问题描述】:

考虑以下代码示例,我将尝试通过两种方式获取结果,如果methodA 没有给我预期的结果,我将尝试methodB

function methodA () {
    console.log('called A');
    return Promise.resolve('not result');
}

function methodB () {
    console.log('called B');
    return Promise.resolve('result');
}

function isValid (result) {
    return result === 'result';
}

async function getResult () {
  let result = await methodA();
  if (!isValid(result)) result = await methodB();
  console.log('result', result);
}

我想使用传统的.then 样式来处理异步函数。

function getResult () {
  return methodA()
  .then((result) => {
    if (isValid(result)) return result;
    return methodB();
  })
  .then((result) => {
    console.log('result', result);
  });
}

我以后可能会添加更多方法(methodCmethodD...)。

有没有办法让getResult 看起来更干净?

JSFiddle

【问题讨论】:

  • 你关心你使用哪个结果吗?例如你总是需要在 C 之前检查 A 先于 B 吗?
  • 另外,只是好奇async / await 在某处引起了问题吗?切换到 Promise 链的动力是什么?
  • async/await 语法的唯一原因是为了让事情看起来更干净(并且让 JS 新手更容易使用 Promise)。除了从单衬里移除大括号并可能将其变成单衬三元组之外,您无能为力让它看起来更干净。
  • @Hunter McMillen,是的。例如,如果 A 有效,则不再执行,否则尝试 B、C、D 等等。
  • Promise.any 可能是一个答案,但实际上并不适合这种情况,因为它会触发所有方法。

标签: javascript ecmascript-6 promise async-await bluebird


【解决方案1】:

您可以一个接一个地解决承诺(按顺序):

function methodA() {
  console.log('called A');
  return Promise.resolve('not result');
}

function methodB() {
  console.log('called B');
  return Promise.resolve('result');
}

function methodC() {
  console.log('called С');
  return Promise.resolve('not result');
}

function getResult() {
  let methods = [methodA, methodB, methodC];

  let op = Promise.resolve();
  methods.forEach(m => op = op.then(result => result == 'result' ? null : m()));

  return op.then(() => console.log('result'));
}

getResult();

在上面的例子中,只有methodAmethodB 会被调用。

【讨论】:

  • 投反对票的请解释我的回答有什么问题?
  • 是的,看起来这是个仇恨者:)。
  • 是的,这个问题和我的回答也被否决了。
【解决方案2】:

function methodA() {
    console.log('called A');
    return Promise.resolve('not result');
}

function methodB() {
    console.log('called B');
    return Promise.reject({ error: true, reason: 'idk' });
}

function methodC() {
    console.log('called C');
    return Promise.resolve('not result');
}

function methodD() {
    console.log('called D');
    return Promise.resolve('result');
}

function addFallback(promise, nextMethod) {
    return promise
    .then(result => result === 'result' ? result : nextMethod())
}

function getResult () {
    let promise = methodA()
    promise = addFallback(promise, methodB);
    promise = addFallback(promise, methodC);
    promise = addFallback(promise, methodD);
    return promise
    .then(result => {
        if (result) { console.log('result', result); }
    });
}

getResult()
.catch(e => { console.log(e)});

【讨论】:

  • 如果任何方法都会抛出错误怎么办?将调用所有其余的 catch 处理程序,但不会处理错误。
  • SO 是否需要处理错误,或者是否只是调用回退方法来处理错误的正确方法?它改变了答案......
  • 只有下一个 catch 处理程序会被调用,顺便说一句......不是所有其他的。
  • 在 OP 示例中,抛出的错误可以在您的示例中在 getResult 函数之外处理(在 async/await 和常规承诺的两种情况下) - 不是。
  • 我认为使用 .catch 进行流量控制是一种反模式。
【解决方案3】:
猜你喜欢
  • 2021-04-10
  • 2016-12-09
  • 2019-12-14
  • 2023-03-11
  • 2014-02-16
  • 1970-01-01
  • 1970-01-01
  • 2011-05-30
  • 2013-06-26
相关资源
最近更新 更多