问题描述
尝试编写一个小的chrome扩展,它依赖于chrome.*
接口的回调重查询功能,我很快就登陆promise和async/await,因为我需要保证某些操作的顺序,同时试图避免回调地狱.
然而,一旦我在一些函数中引入了 async/await,每个使用它们的函数也必须变成一个 async 函数
,以便能够await
返回值.最终,甚至一些全局常量也变成了 promises,例如
const DEBUG = new Promise(function(resolve){chrome.management.getSelf(解决);}).那么(功能(自我){返回 self.installType == 'development';});
然而,现在我需要在任何地方编写 await
并且引入像 if(DEBUG){...}
这样的奇怪错误总是被执行变得太容易了.>
虽然看起来 可以使用 ESLINT 识别错误,在任何地方编写 await
似乎不必要地麻烦,因此我想知道 Javascript 是否有一些我缺少的更好的构造?>
(主观上,我目前对 await/async 的使用似乎倒退了;除非明确等待,否则 Promise 将保持原样,但我似乎更希望在异步函数中默认等待 Promise 并且仅在明确请求时才将其保留为裸承诺.)
由于缺乏类型系统可以轻松捕获此类错误(您考虑过 Typescript 还是 Flow?),您可以使用 Systems Hungarian Notation 用于您的变量名称.选择一个后缀的前缀,例如 P
、Promise
或 $
并将其添加到所有的 promise 变量中,类似于异步函数通常命名为Async
后缀.然后只做像
const debug = await debugPromise
您可以快速看到 if (debug)
很好,但 if (debugPromise)
不好.
一旦我在一些函数中引入了 async/await,每个使用它们的函数也必须变成 async 函数,以便能够等待返回值.最终甚至一些全局常量也变成了 promise
我不会那样做.尝试使尽可能少的函数异步.如果他们自己没有做本质上异步的事情,而只是依赖一些承诺的结果,那么将这些结果声明为函数的参数.一个简单的例子:
//错误异步函数 fetchAndParse(options) {const response = await fetch(options);//做一点事返回结果;}//用法:等待 fetchAndParse(选项)
//好:函数解析(响应){//做一点事返回结果;}//用法:await fetch(options).then(parse)//或解析(等待获取(选项))
同样的模式可以应用于全局变量——要么使它们成为每个函数的显式参数,要么使它们成为包含所有其他函数的闭包的模块函数的参数.然后 await
在模块中只对全局承诺一次,在声明或执行其他任何东西之前,然后使用普通的结果值.
//错误:异步函数日志(行){如果(等待调试承诺)控制台日志(行);}异步函数解析(响应){等待日志(解析")//做一点事返回结果;}...等待解析(...)...
//好:(异步函数 mymodule() {const 调试 = 等待调试承诺;功能日志(行){如果(调试)控制台日志(行);}函数解析(响应){日志(解析")//做一点事返回结果;}...解析(...) ...}());
Trying to write a little chrome extension, which relies on the callback-heavy query functions of the chrome.*
interface, I quickly landed at promises and async/await, as I needed to guarantee the order of certain operations, while trying to avoid callback hell.
However, once I introduced async/await into some functions, every function that used them also had to be turned into an async function
in order to be able to await
the return value. Eventually even some global constants became promises, e.g.
const DEBUG = new Promise(function(resolve){
chrome.management.getSelf(resolve);
}).then(function(self){
return self.installType == 'development';
});
However, now I need to write await
everywhere and introducing weird bugs like if(DEBUG){...}
always being executed becomes way too easy.
While it seems possible to identify the errors using ESLINT, writing await
everywhere seems unnecessarily cumbersome and thus I was wondering if Javascript has some better construct that I am missing?
(Subjectively my current use of await/async seems backwards; Promises are kept as-is unless explicitly awaited, but it seems more desirable to me to have promises awaited by default in async functions and kept as bare promises only when explicitly requested.)
For the lack of a type system that would allow to catch such mistakes easily (did you consider Typescript or Flow?), you can use Systems Hungarian Notation for your variable names. Choose a prefix of suffix like P
, Promise
or $
and add it to all your promise variables, similar to how asynchronous functions are often named with an Async
suffix. Then only do things like
const debug = await debugPromise
where you can quickly see that if (debug)
is fine but if (debugPromise)
is not.
I would not do that. Try to make as few functions asynchronous as possible. If they are not doing intrinsically asynchronous things themselves but only rely on the results of some promises, declare those results as parameters of the function. A simple example:
// Bad
async function fetchAndParse(options) {
const response = await fetch(options);
// do something
return result;
}
// usage:
await fetchAndParse(options)
// Good:
function parse(response) {
// do something
return result;
}
// usage:
await fetch(options).then(parse) // or
parse(await fetch(options))
The same pattern can be applied for globals - either make them explicit parameters of every function, or make them parameters of a module function that contains all others as closures. Then await
the global promises only once in the module, before declaring or executing anything else, and use the plain result value afterwards.
// Bad:
async function log(line) {
if (await debugPromise)
console.log(line);
}
async function parse(response) {
await log("parsing")
// do something
return result;
}
… await parse(…) …
// Good:
(async function mymodule() {
const debug = await debugPromise;
function log(line) {
if (debug)
console.log(line);
}
function parse(response) {
log("parsing")
// do something
return result;
}
… parse(…) …
}());
这篇关于如何不忘记在 Javascript 中到处使用 await?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!