当前位置: 首页 > 面试题库 >

为何流行的JavaScript运行时无法处理看起来像同步的异步脚本?

潘飞英
2023-03-14
问题内容

正如牛仔在此处的评论中所说的,我们所有人都想以类似于以下的样式来编写[非阻塞JavaScript]异步代码:

 try 
 {
    var foo = getSomething();   // async call that would normally block
    var bar = doSomething(foo);  
    console.log(bar); 
 } 
 catch (error) 
 {
    console.error(error);
 }

因此人们提出了解决该问题的方法,例如

  • 回调库(例如async)
  • promises
  • eventemitter
  • streamline
  • domain和
  • generators。

但是,这些都不比上面的同步样式代码更简单易懂。

那么,为什么JavaScript编译器/解释器无法仅不阻塞我们当前称为“阻塞”的语句呢?
那么,如果我们以异步方式编写的话,为什么JavaScript编译器/解释器无法处理AS之上的同步语法呢?”

例如,经过getSomething()上面的处理,编译器/解释器可能会说“此语句是对[文件系统/网络资源/
…]的调用,因此我将做一个笔记来监听来自该调用的响应,并在同时继续处理我的事件循环”。调用返回时,执行可以进行到doSomething()

您仍将保留流行的JavaScript运行时环境的所有基本功能

  • 单螺纹
  • 事件循环
  • “异步”处理的阻塞操作(I / O,网络,等待计时器)

这只是语法上的一个调整,这将允许解释器在IT进行异步操作检测时暂停对任何给定代码的执行,并且不需要回调,而是仅在异步调用后的代码行中继续执行代码,而无需进行回调返回。

正如杰里米所说

JavaScript运行时中没有什么可以抢先暂停给定任务的执行,允许其他一些代码执行一段时间,然后继续执行原始任务

为什么不?(例如,“为什么不可以?” …我对历史课程不感兴趣)

开发人员为什么要关心语句是否被阻塞?计算机用于自动化人类不擅长的事物(例如,编写非阻塞代码)。

你也许可以用

  • 像这样的陈述 "use noblock" ; (有点像"use strict";)打开整个页面代码的“模式”。编辑:"use noblock"; 是一个错误的选择,并误导了一些我试图完全改变普通JavaScript运行时性质的答案。类似的东西'use syncsyntax';可能会更好地描述它。
  • 一种parallel(fn, fn, ...);允许您在运行中并行运行的语句"use syncsyntax"; 模式-例如,允许一次启动多个异步活动
  • 编辑:一种简单的同步样式语法wait(),该语法将代替setTimeout()in "use syncsyntax"; 模式

编辑:

例如,代替编写(标准回调版本)

function fnInsertDB(myString, fnNextTask) {
  fnDAL('insert into tbl (field) values (' + myString + ');', function(recordID) {
    fnNextTask(recordID);
  });
}

fnInsertDB('stuff', fnDeleteDB);

你可以写

'use syncsyntax';

function fnInsertDB(myString) {
  return fnDAL('insert into tbl (field) values (' + myString ');');  // returns recordID
}

var recordID = fnInsertDB('stuff'); 
fnDeleteDB(recordID);

syncsyntax版本的处理方式与标准版本完全相同,但了解程序员的意图要容易得多(只要您了解syncsyntax所讨论的代码会暂停执行)。


问题答案:

为什么不?没有理由,只是没有完成。

在2017年,它 在ES2017中完成:async函数可以用于await等待,无阻塞地等待承诺的结果。如果getSomething返回promise(请注意await)并且位于async函数内部,则可以这样编写代码:

try 
{
    var foo = await getSomething();
    var bar = doSomething(foo);  
    console.log(bar); 
} 
catch (error) 
{
    console.error(error);
}

(我曾假设您只打算getSomething异步,但两者都可能是异步的。)

实时示例(需要最新的浏览器,例如最新的Chrome):

function getSomething() {

    return new Promise((resolve, reject) => {

        setTimeout(() => {

            if (Math.random() < 0.5) {

                reject(new Error("failed"));

            } else {

                resolve(Math.floor(Math.random() * 100));

            }

        }, 200);

    });

}

function doSomething(x) {

    return x * 2;

}

(async () => {

    try

    {

        var foo = await getSomething();

        console.log("foo:", foo);

        var bar = doSomething(foo);

        console.log("bar:", bar);

    }

    catch (error)

    {

        console.error(error);

    }

})();


The first promise fails half the time, so click Run repeatedly to see both failure and success.

您已用NodeJS标记了您的问题。如果将Node
API包装在Promise中(例如,使用promisify),则可以编写异步运行的漂亮的直接同步代码。



 类似资料:
  • 问题内容: 将NodeJS与MongoDB + Mongoose结合使用。 首先,我知道异步非阻塞代码的优点。所以我确实处理回调。但是最后我遇到了以下问题。 可以说我有一个可以随时被用户调用的函数。超级“闪电般的”用户可能几乎同时调用两次。 当然它是这样执行的:查找查询,查找查询,保存查询,保存查询 这完全破坏了应用程序的逻辑(应查找查询,保存查询,查找查询,保存查询)。因此,我决定通过“锁定”特

  • 我正在尝试实现同步调用: 我得到以下例外情况: (节点:22140)UnhandledPromiseRejectionWarning:错误:协议错误(Target.CreateTarget):目标已关闭。在Promise(C:\imageServer\node_modules\puppeteer\lib\connection.js:74:56)在new Promise()在connection.s

  • 是否可以调用一个异步方法,以便它从一个同步的方法异步运行?我不关心它挂起同步调用程序直到它返回,而是希望该方法被异步调用。

  • 问题内容: 我正在尝试从Java执行Bash Shell脚本,并且使用这段代码可以正常运行。 上面的代码异步运行良好。但是我想实现的是同步执行代码。我希望Java进程等到脚本执行完成后再执行下一批代码。 总而言之,我希望在批处理文件(“ myscript.sh”)完成执行 之后 执行“打印语句-脚本成功执行”。 谢谢 问题答案: 你要等待进程结束,这是WAITFOR()这样的

  • 警告试着告诉我什么?我该怎么办? 这是我的代码:它是否使用多线程运行?

  • 然而,在我下面的代码中,我希望在这两个示例中都花费相同的15秒(每个任务5秒),如本文所述。然而,第二个示例只需要5秒,同时运行所有3个示例也需要5秒来完成第二个示例。原来的文章花了5秒,但我把它改成了1秒的延迟,让它更明显。 有没有人能解释一下这是怎么回事,为什么它看起来像线程一样运行?