当我有异步函数时,我应该总是返回一个承诺吗?

few*_*few 7 javascript promise ecmascript-6

当我编写异步函数时,它通常会返回一个承诺:

export const myPromiseFunction = async (params) => {
  // some logic
  return Promise.resolve('resolved-value');
});
Run Code Online (Sandbox Code Playgroud)

但我想知道如果这个函数不返回承诺是否会是一个错误,例如:

export const myPromiseFunction = async (params) => {
  // some logic
  params.map(async (param) => {
    
    await printParam(param);

    async function printParam(par) {
       // do some other stuff
       Printer.print(par);
    });
  });
});

export class Printer {
  public static async print(par) {console.log(par);} // I know it could not be async, but for the sake lets suppose it does
}
Run Code Online (Sandbox Code Playgroud)

这是一个错误/不好的做法吗?或者我们能否找到一个有效且可取的方案?

Jef*_*ica 11

所有async函数都会自动返回 Promise。如果你将一个函数声明为async,它会返回一个 Promise,即使你唯一的return值是一个简单的值,比如字符串或数字。如果你没有显式返回,你的async函数仍然会返回一个值为 的 Promise undefined

事实上,函数体async常见的是返回一个简单的值而不是一个 Promise;假设你的功能是async因为你await在其中消费了承诺。因此,即使返回值 5,返回值也是一个 Promise(解析为 5),表示来自await函数中任何表达式的潜在延迟。

您不必在async函数中显式返回 Promise 对象,如果您只是包装一个简单的值(例如'resolved-value'. async相反,如果您始终返回 Promise(可能使用 Promise.resolve)并且从不同步抛出其中的错误,则可以使普通函数表现得像函数一样。

async function myFunction() {
  makeSomeCall();            // Happens immediately.

  await someOtherPromise();  // myFunction returns a Promise
                             // before someOtherPromise resolves; if it
                             // does without error, the returned Promise
  return 5;                  // resolves to 5.
}

/** Behaves the same as the above function. */
function myFunctionButNotAsync() {
  try {
    makeSomeCall();

    // If you didn't have someOtherPromise() to wait for here, then
    // this is where Promise.resolve(5) would be useful to return.
    return someOtherPromise().then(() => 5);
  } catch (e) {
    return Promise.reject(e);
  }
}
Run Code Online (Sandbox Code Playgroud)

尽管如此,您可能有机会显式返回一个 Promise 对象(例如由 PromisePromise.all返回函数生成的对象或单独的 Promise 返回函数),然后该对象遵守类似于所Promise.resolve()观察到的规则:如果从函数返回的对象async是 Promise,或者有一个then函数,那么该async函数返回的自动 Promise 将等待您通过 传回的特定 Promise 或 Promise-like 对象return

async function myFunction() {
  makeSomeCall();            // Happens immediately.

  await someOtherPromise();  // myFunction returns a Promise
                             // before someOtherPromise resolves; if it
                             // does without error, the returned Promise
  return 5;                  // resolves to 5.
}

/** Behaves the same as the above function. */
function myFunctionButNotAsync() {
  try {
    makeSomeCall();

    // If you didn't have someOtherPromise() to wait for here, then
    // this is where Promise.resolve(5) would be useful to return.
    return someOtherPromise().then(() => 5);
  } catch (e) {
    return Promise.reject(e);
  }
}
Run Code Online (Sandbox Code Playgroud)

在相关意义上,这就是为什么return await被视为冗余的原因,尽管如所描述的,如果包装的 Promise 被拒绝,它确实会对您看到的堆栈跟踪产生影响。


小智 0

简短的回答:不,async函数不必返回 Promise。实际上,通常您不会返回 Promise 对象(除非您链接异步事件)。

要做asyncawait就是等待返回 Promise 的响应。

您的第一个代码示例实际上返回了一个已解决的Promise。但是如果 Promise 没有得到正确解决会发生什么?

最好调用一个从另一个async函数返回 Promise 的函数:

function getRequestResult() {
  return new Promise(resolve => {
    setTimeout(() => {
      resolve('request sent');
    }, 2000);
  });
}

async function sendMyRequest() {
  console.log('Sending request');
  const result = await getRequestResult();
  console.log(result);
  // expected output: "resolved"
}
Run Code Online (Sandbox Code Playgroud)

您可以通过这种方式发送拒绝/错误getRequestResult(),还可以管理如何通过调用来管理这些错误sendMyRequest()(请参阅https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/await)。