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

Using resolved promise data synchronously

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

我读过的几乎所有示例都在链式 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
}

我想知道是否有任何方法可以在 'normal' 同步代码

中使用已解决承诺中的数据
 const result = Library.functionReturningAPromise()

 // do something to resolve the promise

 const obj = new Example(result)

或者如果您需要始终 'wrap' 所有 您的逻辑使用 async 函数中已解决承诺的数据。

如果您想 "leave" 异步上下文,您可以等待 Promise 完成,然后 then() 调用您的 "regular" 函数之一作为回调。

我能理解异步编码风格可能非常混乱,但实际上这正是 then(function () {}) 所做的。

如果您更容易理解或使用此编码风格,则它在功能上是等效的。

function first() {
    console.log("sync!");
    doAsync();
}

function doAsync() {
    console.log("now we're async!");
    Library.functionReturningAPromise().then(second);
}

function second() {
    console.log("sync again!");
    // ...
}

I want to know if there is any way at all to use the data from a resolved promise in 'normal' synchronous code

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

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

or if you need to always 'wrap' all your logic that uses the data from a resolved promise in an async function.

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

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


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

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

    // do the rest of the logic
}
  1. 所有使用 async return 承诺声明的函数。这是您从他们那里获得的唯一一种 return 价值。如果调用者正在寻找 return 值或想知道异步操作何时完成或正在寻找错误,他们必须使用 returned promise with .then(), .catch() 或在 async 函数中再次使用 await
  2. 如果您正在等待的承诺被拒绝,它实际上将抛出并中止函数的其余执行,然后 return 拒绝 returned 承诺。
  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);
});

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

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

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