同步使用已解决的承诺数据

新手上路,请多包涵

我正在学习 promises,我绝对想确保在继续之前了解它们的用法。我正在使用一个库来提供在线服务,该服务具有返回承诺的功能。

我阅读的几乎所有示例都使用链式 then() 函数中的已解析数据

const result = Library.functionReturningAPromise()
result.then(function(res) {
    const obj = new Example(res)
    return obj
}).then(function(ob) {
    // do the rest of the logic within these then() functions
})

或者在 async 函数中使用解析后的数据

async function test() {
    const result = await Library.functionReturningAPromise()
    const obj = new Example(result)

    // do the rest of the logic
}

我想知道是否有任何方法可以在“正常”同步代码中使用已解决承诺中的数据

 const result = Library.functionReturningAPromise()

 // do something to resolve the promise

 const obj = new Example(result)

或者,如果您需要始终在 async 函数中“包装” 所有 使用来自已解决承诺的数据的逻辑。

原文由 myol 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 379
2 个回答

我想知道是否有任何方法可以在“正常”同步代码中使用已解决承诺中的数据

在处理异步响应时,没有办法编写完全同步的代码。一旦任何操作是异步的,您就必须使用异步技术来处理响应,并且不能对其进行同步编程。您必须学习异步编程。

您显示的两个选项( .then()async/await )是您处理返回承诺的两个选择。

或者,如果您需要始终“包装”所有使用异步函数中已解决承诺的数据的逻辑。

如果您想使用 await 以便您可以编写看起来同步的代码来处理承诺,那么所有这些代码都必须在 async 函数中。而且,一旦您离开该函数的范围(例如想要返回一个值),您就会从 async 函数返回一个承诺,并且必须再次处理该承诺。

没有办法解决这个问题。这只是在 Javascript 中必须学习的东西。一段时间后,它变成了第二天性。


如您所知,您可以使用 asyncawait 来获得一些看起来同步的逻辑流,但是有一些事情可以确保您在执行此操作时理解。从你的例子:

 async function test() {
    const result = await Library.functionReturningAPromise()
    const obj = new Example(result);

    // do the rest of the logic
}

  1. async 声明的所有函数返回一个承诺。这是您从他们那里获得的唯一回报。如果调用者正在寻找返回值或想知道异步操作何时完成或正在寻找错误,他们必须使用返回的承诺 .then().catch() 或再次使用 awaitasync 函数中。
  2. 如果您正在等待的承诺被拒绝,它实际上将抛出并中止该函数的其余执行,然后返回拒绝返回的承诺。
  3. 如果您希望执行流程在拒绝承诺时中止并且调用者将处理拒绝,那么这一切都很好。
  4. 但是,如果呼叫者没有处理拒绝,则需要有人处理。如果您正在使用 await 并且您需要在本地处理拒绝,那么您需要将它们包装在 try/catch (与同步异常非常相似的语法)中。

这是使用 try/catchawait 在本地处理错误的示例:

 async function test() {
    try {
        const result = await Library.functionReturningAPromise();
        const obj = new Example(result);

        // do the rest of the logic
    } catch(e) {
        // handle promise rejection here
    }
}

下面是调用者处理错误的示例:

 async function test() {
    const result = await Library.functionReturningAPromise();
    const obj = new Example(result);

    // do the rest of the logic
}

test().then(() => {
    console.log("all done");
}).catch(err => {
    console.log(err);
});

原文由 jfriend00 发布,翻译遵循 CC BY-SA 4.0 许可协议

如果 将它们的使用包装在返回默认值的函数中,则可以使用 async/awaitthen() 的组合来同步编程。

下面是一个使用记忆来返回结果或在需要时查询结果的示例:

 const scope = {
  // someResult is wrapped in an object so that it can be set even if it's a primitive
  // (e.g. number / string).
  someResult: null,
};

function getResult() {
  if (scope.someResult !== null) {
    // If we already have a result, return it. No need to query Library again.
    return scope.someResult;
  }

  // Note: This example doesn't implement debouncing (avoiding repeated Library queries while
  // Library is still being queried).
  queryLibrary().then(result => {
    if (scope.someResult === null) {
      // If the Library call succeeded and we haven't already stored its result, store it.
      scope.someResult = result;
      console.log('We have a result now!', getResult());
    }
  });

  return scope.someResult;
}

async function queryLibrary() {
  const result = await functionReturningAPromise();
  // Do some stuff with result in a nice async / await way.
  result.push(9000, 1336);
  return result;
}

/** This is some complicated async function from Library. */
async function functionReturningAPromise() {
  return [419, 70];
}

// Calling getResult() will return either null or a list of numbers.
console.log('Do we have a result yet?', getResult());

原文由 Acorn1010 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题