【问题标题】:Is there a way to write asynchronous code/function without any involvement of Web APIs?有没有办法在不涉及 Web API 的情况下编写异步代码/函数?
【发布时间】:2021-10-07 04:46:22
【问题描述】:

我知道这听起来很愚蠢,因为 javascript 是单线程的,但我不禁想到一个函数会花费大量时间而无需像这样的 Web API 参与

console.log("start")

function apple() {
  let appleCount = 10;
  while (appleCount < 1000000) {
    appleCount = appleCount + 10;
    appleCount = appleCount * 0.0000052
  }
}

apple();
console.log("end")

那么有没有办法异步运行这个苹果函数...我尝试在浏览器中运行此代码但没有得到任何结果...帮帮我..

【问题讨论】:

  • 使用服务人员
  • 你期待输出:“开始,结束,苹果完成” insted “开始,苹果完成,结束”吗?使用 async / await 功能是可能的。
  • 我期待开始,结束,苹果完成......我认为异步/等待是不可能的
  • 运行 100% 纯 Javascript 以使其不会阻塞主线程的唯一方法是在不同的线程中运行它(在 nodejs 中,使用 WorkerThread)。正如您似乎知道的那样,主线程在单个线程中运行您的 Javascript,因此任何简单的 Javsacript 都会占用该单个线程。要让它不占用那个单一线程,你必须在不同的线程中运行它,要么是 WorkerThread,要么是另一个进程。
  • @AbHisheKThaKur,是的,你说得对,我的错。

标签: javascript node.js asynchronous-javascript


【解决方案1】:

运行像 apple() 函数这样的 100% 纯 Javascript 以便它不会阻塞主线程的唯一方法是在不同的线程中运行它(在 nodejs 中,使用 WorkerThread)或一个不同的过程。

您似乎知道主线程在单个线程中运行您的 Javascript,因此任何纯 JavaScript 都在运行时占用该单个线程。为了让它不占用那个单线程并阻塞事件循环,你必须在不同的线程中运行它,要么是WorkerThread,要么是在另一个进程中运行。


可以使用诸如setTimeout(apple, 100)setImmediate(apple) 甚至Promise.resolve().then(apple) 之类的计时技巧来更改代码运行的时间(延迟启动时),但所有这些计时技巧所做的只是在代码开始运行时更改。在所有这些情况下,当它运行时,它仍然会阻塞并占用主线程,并在运行时阻塞事件循环。


仅供参考,nodejs 中有许多异步操作不一定是 Web API。例如,有异步和非阻塞的异步文件 API 和加密 API。因此,您的问题应该修改为不仅仅指 Web API,还指任何异步 API。

【讨论】:

  • bro setTimeout 和 setImmediate 是 Web API 的一部分
  • @AbHisheKThaKur - 而且,我要解释的是,即使使用这些 API,它也不能避免阻塞单线程,因为它们所做的只是在单线程被阻塞时进行更改。仅供参考,webAPI 在 nodejs 的世界中并不是一个定义明确的术语。它可能在浏览器中有意义,但这是nodejs。 nodejs 中有很多 API 是异步的,并且在任何定义下都不是 webAPI,例如加密和文件 API。
  • @AbHisheKThaKur - 这个答案能解释/回答你的问题吗?
  • 只是想提一下,在 nodejs 中,libuv 使用 4 个线程,这使得加密和文件 API 可以异步工作......虽然不确定
  • @AbHisheKThaKur - 是的,这些是 OS 本机线程,nodejs 在其中运行文件和加密 API 的本机代码实现。这不是在这些线程中运行的纯 Javascript,而是本机 C/C++ 代码。 nodejs 中的所有非阻塞、异步操作都有一些本机代码部分,它们要么使用非阻塞 OS API(如网络),要么在本机 OS 线程中运行。他们使用事件循环来协调从这些其他线程到主 Javascript 线程的完成。
【解决方案2】:

那么有没有办法异步运行这个苹果函数?

如果你不想等到你的apple函数完成,那么你可以使用Async Functions

注意:异步/承诺不是真正的异步。

console.log("start")

async function apple() {
  let appleCount = 10;
  while (appleCount < 1000000) {
    appleCount = appleCount + 10;
    appleCount = appleCount * 0.0000052
  }
}

apple().then(() => console.log("Apple completed"));
console.log("end")

但是如果你想在另一个线程上运行它,那么你应该使用Workers

https://developer.mozilla.org/en-US/docs/Web/API/Service_Worker_API

【讨论】:

  • 简单地将async 添加到function 不会使其异步。这只是意味着返回的值将由 JS 运行时自动包装在 Promise&lt;T&gt; 中。
  • @Dai 是的,我明白了。它不是真正的异步,因为使用回调会产生一种异步的错觉。如果他不想等到apple 函数完成,Async 函数就可以工作。但如果他想将其作为真正的异步运行,那么 Service Worker 将是一个不错的选择。
【解决方案3】:

你只需要返回承诺。

function double(num) {
  return Promise.resolve(num * 2);
}

function add5(num){
  return Promise.resolve(num + 5);
}

double(1)// 2
    .then(add5)// 7
    .then(double)// 14
    .then(console.log)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-12-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-11-29
    • 1970-01-01
    • 2016-06-01
    • 1970-01-01
    相关资源
    最近更新 更多