如何在async/await语法中拒绝?

Pho*_*nix 234 javascript asynchronous typescript es6-promise ecmascript-2017

如何拒绝async/await函数返回的promise?

例如,最初

foo(id: string): Promise<A> {
  return new Promise((resolve, reject) => {
    someAsyncPromise().then((value)=>resolve(200)).catch((err)=>reject(400))
  });
}
Run Code Online (Sandbox Code Playgroud)

转换为async/await

async foo(id: string): Promise<A> {
  try{
    await someAsyncPromise();
    return 200;
  } catch(error) {//here goes if someAsyncPromise() rejected}
    return 400; //this will result in a resolved promise.
  });
}
Run Code Online (Sandbox Code Playgroud)

那么,在这种情况下,我怎么能正确地拒绝这个承诺呢?

T.J*_*der 273

最好的办法是到throw一个Error包装的价值,这将导致与被拒绝的承诺,Error包装的价值:

} catch (error) {
    throw new Error(400);
}
Run Code Online (Sandbox Code Playgroud)

您也可以只是throw值,但是没有堆栈跟踪信息:

} catch (error) {
    throw 400;
}
Run Code Online (Sandbox Code Playgroud)

或者,返回一个被拒绝的promise,其中包含Error值:

} catch (error) {
    return Promise.reject(new Error(400));
}
Run Code Online (Sandbox Code Playgroud)

(或者只是return Promise.reject(400);,但是再一次,没有上下文信息.)

(在你的情况,因为你正在使用TypeScriptfoo的retrn值Promise<A>,你会使用return Promise.reject<A>(400 /*or error*/);)

在一个async/ await情境中,最后一个可能是一个语义上的不匹配,但它确实有效.

如果你抛出一个Error,那么任何消耗你fooawait语法结果的东西都会很好:

try {
    await foo();
} catch (error) {
    // Here, `error` would be an `Error` (with stack trace, etc.).
    // Whereas if you used `throw 400`, it would just be `400`.
}
Run Code Online (Sandbox Code Playgroud)

  • 由于async/await是关于将异步流程恢复为同步语法,因此`throw`优于`Promise.reject()`IMO.是否"扔400"是一个不同的问题.在OP中,它拒绝了400,我们可以争辩说它应该拒绝"错误". (11认同)
  • 是的,但是,如果您的代码链真的使用async/await,那么您将.....很难在这里输入,让我演示作为答案 (2认同)

Dav*_*vid 127

还应该提到的是,您可以catch()在调用异步操作之后简单地链接一个函数,因为在引擎盖下仍然会返回一个promise.

await foo().catch(error => console.log(error));
Run Code Online (Sandbox Code Playgroud)

这样,try/catch如果您不喜欢它,可以避免使用语法.

  • 我不明白为什么这应该是公认的答案.不仅接受的答案更清晰,而且它还可以在一个例程中处理所有可能的"等待"故障.除非每个'等待'都需要非常具体的情况,否则我不明白你为什么要这样抓住它们.只是我谦虚的意见. (6认同)
  • 我喜欢尽可能使用它,但是如果 catch 的预期行为是从外部作用域(调用 foo() 的作用域)返回,**那么您不能使用此解决方案**。在这种情况下,我被迫使用 try-catch 块,因为 catch 的 lambda 函数内的 return 语句只会从 lambda 函数返回,而不是从外部作用域返回。 (4认同)
  • @AshishRawat 不正确。如果没有“await”关键字,待处理的承诺将返回到等待变量。使用“await”关键字,它可以确保(如果 Promise 被解析且没有错误)返回值是已解析的 Promise 结果。 (3认同)
  • 因此,如果我想拒绝我的“async”函数,我会抛出异常,然后用“.catch()”很好地捕获它,就像我返回“Promise.reject”或调用“reject”一样。我喜欢! (2认同)
  • @jablesauce 对于我的用例,我不仅需要单独捕获每个 `await` 失败,而且我还需要使用基于 Promise 的框架,该框架在错误时拒绝承诺。 (2认同)

And*_*ndy 10

您可以创建一个包含promise包装函数,如果没有错误则返回包含数据的数组,如果有错误则返回错误.

function safePromise(promise) {
  return promise.then(data => [ data ]).catch(error => [ null, error ]);
}
Run Code Online (Sandbox Code Playgroud)

ES7异步函数中使用它:

async function checkItem() {
  const [ item, error ] = await safePromise(getItem(id));
  if (error) { return null; } // handle error and return
  return item; // no error so safe to use item
}
Run Code Online (Sandbox Code Playgroud)

  • 看起来像是尝试使用可爱的 Go 语法,但没有太多优雅。我发现使用它的代码被混淆了,足以从解决方案中吸取价值。 (3认同)
  • 这个模式在这个包https://github.com/scopsy/await-to-js中得到了发展 (3认同)

uni*_*nal 6

这不是对@TJ Crowder 的回答。只是对评论的评论“实际上,如果异常将被转换为拒绝,我不确定我是否真的为它感到困扰,如果它是一个错误。我只抛出错误的原因可能不适用。 ”

如果您的代码正在使用async/ await,那么使用Error代替来拒绝仍然是一个好习惯400

try {
  await foo('a');
}
catch (e) {
  // you would still want `e` to be an `Error` instead of `400`
}
Run Code Online (Sandbox Code Playgroud)


Ozz*_*ant 5

编写异步函数的一种更好的方法是从头开始返回一个未决的Promise,然后在Promise的回调中处理拒绝和解决方案,而不是随便吐出错误时被拒绝的Promise。例:

async foo(id: string): Promise<A> {
    return new Promise(function(resolve, reject) {
        // execute some code here
        if (success) { // let's say this is a boolean value from line above
            return resolve(success);
        } else {
            return reject(error); // this can be anything, preferably an Error object to catch the stacktrace from this function
        }
    });
}
Run Code Online (Sandbox Code Playgroud)

然后,您只需在返回的Promise上链接方法:

async function bar () {
    try {
        var result = await foo("someID")
        // use the result here
    } catch (error) {
        // handle error here
    }
}

bar()
Run Code Online (Sandbox Code Playgroud)

来源-本教程:

https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Promise

  • 该问题专门询问有关使用异步/等待的问题。不使用诺言 (5认同)

Ped*_*nço 5

我有一个建议,以一种新颖的方法正确处理拒绝,而无需多个 try-catch 块。

import to from './to';

async foo(id: string): Promise<A> {
    let err, result;
    [err, result] = await to(someAsyncPromise()); // notice the to() here
    if (err) {
        return 400;
    }
    return 200;
}
Run Code Online (Sandbox Code Playgroud)

哪里 应从导入to.ts函数:

export default function to(promise: Promise<any>): Promise<any> {
    return promise.then(data => {
        return [null, data];
    }).catch(err => [err]);
}
Run Code Online (Sandbox Code Playgroud)

学分转到以下链接中的 Dima Grossman 。