- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
在 javascript 中,是否可以在同步函数中使用浏览器内置的 sha256 哈希( https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto/digest#Converting_a_digest_to_a_hex_string )?
理想情况下,我想做类似的事情
String.prototype.sha256 = function() {
// ...
return hash
}
(async() => {hash = await digestMessage(message); return hash})()
之类的东西,但我只能取回 promise 对象。
最佳答案
TL; 博士
不,不可能在 JavaScript 中将异步函数包装在同步函数中并传播结果。请看这个excellent blog post on sync vs. async functions in various languages .要点是 JavaScript 是(许多语言中的)一种,其中异步函数由于语言运行方式的性质而具有传染性。
异步内置函数是 JS 的救星
JavaScript 在一个线程上运行。更具体地说,与特定网页相关的所有 JavaScript 都在同一线程上运行,以保证只有 一 一行 JS 将在任何特定时刻运行。这让我们尼安德特人的 Web 程序员无需负责编写互斥锁和原子操作等同步代码,以免多个线程同时写入同一内存并导致数据损坏甚至崩溃。
但是,我们只有一个线程来操作网页上的视觉元素并运行各种业务逻辑,例如加密/解密和数据管理,这有点糟糕。这一切都可能会变慢并损害用户体验。但是异步函数如何解决这个问题呢?拿这个功能:
function syncGenRSAKey() {
// fancy math stuff...
return generatedKey;
}
让我们让它异步(基于 promise ):
function asyncGenRSAKey() {
return new Promise((resolve, reject) => {
resolve(syncGenRSAKey());
});
}
希望你的直觉不会告诉你基于 Promise 的函数在这里更快。发生的一切是这样的:
asyncGenRSAKey()
Promise
构造函数(resolve, reject) => { ... }
传递给它的回调函数 syncGenRSAKey()
功能syncGenRSAKey()
)是用 JavaScript 编写的,无论从哪里调用它,它都会在主线程上消耗时间。这意味着它将阻止浏览器跳转到其他 JavaScript,即事件处理程序。浏览器还会在主线程上渲染页面,因此它会卡住页面上的几乎所有内容(一些 CSS 动画被特别渲染),而
genRSAKey()
在跑。用户可以悬停按钮,按钮背景和鼠标光标都不会更新。
crypto.subtle
下提供的函数使用浏览器实现者选择的任何语言编写:C++、Rust 等。这些函数不是由 JavaScript 引擎运行的,它们是其中的一部分。它们可以产生尽可能多的操作系统线程,因为它们可以在您的计算机在给定时刻可以空闲的尽可能多(或尽可能少)的 CPU 内核上运行。这意味着 key 生成代码可以并且经常会与您的一堆 JavaScript 代码和页面渲染选项完全并行运行,然后浏览器将在 key 准备好并且任何当前正在运行的 JavaScript 完成运行时回调到您的 JavaScript ,触发要解决的 promise (如果生成 key 时出错,则拒绝),然后可以启动链接到生成 key 的任何 promise 中的代码。
Now, is this really necessary for
SHA-256
checksums in particular? No. In fact I myself still have a GitHub PR I've been putting off because I got tired of promisifying everything (which included some very complex Angular components) because I compute one f**king hash when the user opens a modal. This aside is for you, Suzanne.
async
的澄清/
await
在 JavaScript 中
async
和
await
关键字是纯粹的语法糖。它们不能让你做任何你以前不能使用老式 promise 链做的事情,就像 promise 不能让你做任何你不能用好的 ole 嵌套回调函数做的事情一样。
async
/
await
只是让你的代码更简洁 10 倍。最后,与使用嵌套回调相比,promise 实际上会产生少量的运行时开销,因为 Promise 具有各种状态以方便将它们很好地链接起来并且是堆分配的;
async
/
await
,我听说,可以通过让 JS 引擎更容易地查看异步代码的整体上下文和使用变量的位置等,并进行优化来撤消这一小小的后退。
async
的一些常见示例/
await
正确使用。它们是用 TypeScript 编写的,以明确返回类型,但如果您只是去掉
: Whatever
s 它变成了 JavaScript。
function withoutAsyncAwait(): Promise<number> {
// Note that the reject callback provided to us by the Promise
// constructor is rarely useful because the promise will
// automatically be rejected if our callback throws an error,
// e.g., if the Math.random() throws an error.
return new Promise((resolve, reject) => resolve(Math.random()));
// Could be (ignore the reject callback):
// return new Promise(resolve => resolve(Math.random()));
}
async function withAsyncAwait(): Promise<number> {
// If any synchronous code inside an async function throws an
// error, a promise will still be returned by the async function,
// but it will be rejected (by far the only desirable behavior).
// The same is true if an await'ed promise rejects.
return Math.random();
}
您不能(以及为什么要)避免
Promise
构造函数,如果您要包装传统的基于回调的
function timeout(milliseconds: number): Promise<void> {
return new Promise(resolve => window.setTimeout(resolve, milliseconds));
}
条件异步步骤
async
/
await
这意味着您必须复制同步代码或将其全部包装在 promise 链中
function doStuffWithoutAsyncAwait1(needToMakeAsyncRequest: boolean): Promise<void> {
// Might be a no-op promise if we don't need to make a request before sync code
const promise = needToMakeAsyncRequest ? makeAsyncRequest() : Promise.resolve();
return promise.then(() => {
// tons of code omitted here, imagine like 30 lines...
});
}
function doStuffWithoutAsyncAwait2(needToMakeAsyncRequest: boolean): Promise<void> {
// Or we can just write the sync code twice, wrapping it in a promise in the branch
// where we make an async request first. This sucks because our 30 lines of sync
// code is written twice AND one of the times it is nested/indented inside of both
// an if-statement and a .then() call
if (needToMakeAsyncRequest) {
return makeAsyncRequest().then(() => {
// tons of code omitted here, imagine like 30 lines...
});
}
// tons of code omitted here, imagine like 30 lines...
}
async function cmereAsyncAwaitYouSexyBoiYou(needToMakeAsyncRequest: boolean): Promise<void> {
if (needToMakeAsyncRequest) {
// Brings tears to my eyes 🥲
await makeAsyncRequest();
}
// tons of code omitted here, imagine like 30 lines...
}
结合 async/await 和现有的 promise 机制
async
/
await
不是 Elixir 。它使编写一系列异步步骤变得非常干净
async function takes12SecondsTotal(): Promise<[string, string]> {
const result1 = await takes7Seconds();
const result2 = await takes5Seconds(); // will not get here till 1st result is done
return [result1, result2];
}
async function takes7SecondsTotal(): Promise<[string, string]> {
// Both inner functions start doing stuff immediately and we just wait for them
// both to finish
const [result1, result2] = await Promise.all([
takes7Seconds(),
takes5Seconds()
]);
return [result1, result2];
}
function nottttttActuallyyyyyTheSammeeeeIKnowIKnowScrewErrorHandling(): Promise<[string, string]> {
// We are almost there! However, we just introduced a potential sh!tstorm by reducing down our
// code and getting rid of async/await: we now have the assumption that both the takes7Seconds()
// and takes5Seconds() calls DO return promises... but they might have synchronous code and the
// beginning of them that could throw an error because the author screwed up and then they will
// blow up SYNCHRONOUSLY in our face and this function will also blow up SYNCHRONOUSLY and it
// will continue up the call stack until it hits a try-catch or it reaches all the way out and
// the JS engine stops it and logs it in the dev tools
return Promise.all([
takes7Seconds(),
takes5Seconds()
]);
// Let me illustrate:
function takes5Seconds(): Promise<string> {
const now = new Date; // Trivia: you don't need constructor parenthesis if no parameters
if (now.getDay() === 6 && now.getHours() === 21) { // 9pm on a Saturday
// Synchronous error
throw Error("I ain't workin' right now, ok?")
}
// Returns a promise, whose rejection will be handled by the promise chain, so an
// "asynchronous" error (but this function could also throw a synchronous error, you
// never know)
return doSomeWork();
}
}
function thisIsFunctionallyTheSame(): Promise<[string, string]> {
try {
return Promise.all([
takes7Seconds(),
takes5Seconds()
]);
} catch (err) {
// catch any synchronous error and gift-wrap it in a promise to protect whoever calls
// us from a synchronous error explosion
return Promise.reject(err);
}
}
async function justBeSmartAndUseAsync(): Promise<[string, string]> {
// Even though we don't use await at all, async functions act as a stalwart line of defense,
// stopping any synchronous errors thrown from continuing up the callstack, implicitly
// catching them and making sure we return a promise NO MATTER WHAT (implicitly does what
// I did above but the browser probably does it better since async functions are part of the
// language spec and lots of work has been and will be put into optimizing them)
return Promise.all([
takes7Seconds(),
takes5Seconds()
]);
}
我们甚至可能希望同时运行多个异步步骤序列。
async function youCouldBeForgivenForDoingThis(): Promise<void> {
// Please edit this answer if I'm wrong, but last time I checked, an await keyword holds up
// the entire expression it's part of--in our case, that means the entire Promise.all(...)
// expression. The doSomethingUnrelated() will not even start running until writeCode()
// finishes
await Promise.all([
pushCodeToGitHub(await writeCode()),
doSomethingUnrelated()
]);
}
async function armedWithEsotericJSKnowledge(): Promise<void> {
// Also please note I just await the Promise.all to discard the array of undefined's and
// return void from our async function
await Promise.all([
writeCode().then(code => pushCodeToGitHub(code)),
doSomethingUnrelated()
]);
}
永远不要害怕将 promise 存储在变量中,或者混合使用
async
箭头函数变成传统的
.then()
根据需要获得最智能的代码的 promise 链。
.then()
回调,你可以返回一个类型
T
或
Promise<T>
和 promise
T
被传递到下一个
.then()
链上。
T
可能是
number
或任何其他类型的。
async
函数做同样的事情
function getNumber(): number {
return 420;
}
async function getNumberAsync(): Promise<number> {
return getNumber(); // auto-wrap it in a promise cuz we're an async function
}
async function idkJavaScriptButIWantToMakeSureIGetThatNumber(): Promise<number> {
return await getNumberAsync(); // this IS fine, really
}
async function iKNOWJavaScript(): Promise<number> {
return getNumberAsync(); // this will NOT return Promise<Promise<number>> because async unwraps it
}
function iLikeToBlowUpRandomly(): Promise<number> {
if (Math.random() > 0.5) {
// This is not an async function so this throw clause will NOT get wrapped in a rejected promise
// and returned pleasantly to the caller
throw new Error("boom");
}
return getNumberAsync();
}
async function iHandleMyProblemsAndAlwaysFulfillMyPromises(): Promise<number> {
try {
return iLikeToBlowUpRandomly();
} catch (err) {
// This will always catch the "boom" explosions, BUT, if iLikeToBlowUpRandomly() returns a
// rejected promise, it will sneakily slip through our try-catch because try-catches only
// catch THROWN errors, and whoever called us will get a bad promise even though we
// promised (haha) we would only ever return fulfilled promises containing numbers
return -1;
}
}
async function iActuallyHandleMyProblemsAndAlwaysFulfillMyPromises(): Promise<number> {
try {
// Bam! The normally extraneous await here brings this promise into our pseudo-synchronous
// async/await code so if it was rejected, it will also trigger our catch branch just like
// a synchronous error would
return await iLikeToBlowUpRandomly();
} catch (err) {
return 3522047650; // call me if you have job offers 😉 but I'm kinda busy rn and spent way too much time on this
}
}
关于javascript - 在同步函数中使用 javascript `crypto.subtle`,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57626477/
我正在实现 IMAP 客户端,但 IMAP 邮箱同步出现问题。 首先,可以从 IMAP 服务器获取新邮件,但我不知道如何从邮箱中查找已删除的邮件。 我是否应该从服务器获取所有消息并将其与本地数据进行比
我研究线程同步。当我有这个例子时: class A { public synchronized void methodA(){ } public synchronized void met
嗨,我做了一个扩展线程的东西,它添加了一个包含 IP 的对象。然后我创建了该线程的两个实例并启动它们。他们使用相同的列表。 我现在想使用 Synchronized 来阻止并发更新问题。但它不起作用,我
我正在尝试使用 FTP 定期将小数据文件从程序上传到服务器。用户从使用 javascript XMLHttpRequest 函数读取数据的网页访问数据。这一切似乎都有效,但我正在努力解决由 FTP 和
我不知道如何同步下一个代码: javascript: (function() { var s2 = document.createElement('script'); s2.src =
关闭。这个问题需要更多focused .它目前不接受答案。 想改进这个问题吗? 更新问题,使其只关注一个问题 editing this post . 关闭 7 年前。 Improve this qu
一 点睛 1 Message 在基于 Message 的系统中,每一个 Event 也可以被称为 Message,Message 是对 Event 更高一个层级的抽象,每一个 Message 都有一个
一 点睛 1 Message 在基于 Message 的系统中,每一个 Event 也可以被称为 Message,Message 是对 Event 更高一个层级的抽象,每一个 Message 都有一个
目标:我所追求的是每次在数据库中添加某些内容时(在 $.ajax 到 Submit_to_db.php 之后),从数据库获取数据并刷新 main.php(通过 draw_polygon 更明显)。 所
我有一个重复动画,需要与其他一些 transient 动画同步。重复动画是一条在屏幕上移动 4 秒的扫描线。当它经过下面的图像时,这些图像需要“闪烁”。 闪烁的图像可以根据用户的意愿来来去去和移动。它
我有 b 个块,每个块有 t 个线程。 我可以用 __syncthreads() 同步特定块中的线程。例如 __global__ void aFunction() { for(i=0;i #
我正在使用azure表查询来检索分配给用户的所有错误实体。 此外,我更改了实体的属性以声明该实体处于处理模式。 处理完实体后,我将从表中删除该实体。 当我进行并行测试时,可能会发生查询期间,一个实体已
我想知道 SQLite 是如何实现它的。它基于文件锁定吗?当然,并不是每个访问它的用户都锁定了整个数据库;那效率极低。它是基于多个文件还是仅基于一个大文件? 如果有人能够简要概述一下 sqlite 中
我想post到php,当id EmpAgree1时,然后它的post变量EmpAgree=1;当id为EmpAgree2时,则后置变量EmpAgree=2等。但只是读取i的最后一个值,为什么?以及如何
CUBLAS 文档提到我们在读取标量结果之前需要同步: “此外,少数返回标量结果的函数,例如 amax()、amin、asum()、rotg()、rotmg()、dot() 和 nrm2(),通过引用
我知道下面的代码中缺少一些内容,我的问题是关于 RemoteImplementation 中的同步机制。我还了解到该网站和其他网站上有几个关于 RMI 和同步的问题;我在这里寻找明确的确认/矛盾。 我
我不太确定如何解决这个问题......所以我可能需要几次尝试才能正确回答这个问题。我有一个用于缓存方法结果的注释。我的代码目前是一个私有(private)分支,但我正在处理的部分从这里开始: http
我对 Java 非常失望,因为它不允许以下代码尽可能地并发移动。当没有同步时,两个线程会更频繁地切换,但是当尝试访问同步方法时,在第二个线程获得锁之前以及在第一个线程获得锁之前再次花费太长时间(比如
过去几周我一直在研究java多线程。我了解了synchronized,并理解synchronized避免了多个线程同时访问相同的属性。我编写此代码是为了在同一线程中运行两个线程。 val gate =
我有一个关于 Java 同步的简单问题。 请假设以下代码: public class Test { private String address; private int age;
我是一名优秀的程序员,十分优秀!