js 只有一个线程,那么用了异步,等待 io 的时候,不用消耗线程吗?没有一个守护线程去等待 io 吗 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
find456789
V2EX    问与答

js 只有一个线程,那么用了异步,等待 io 的时候,不用消耗线程吗?没有一个守护线程去等待 io 吗

  •  
  •   find456789 2020-04-30 14:42:09 +08:00 1819 次点击
    这是一个创建于 1988 天前的主题,其中的信息可能已经有所发展或是发生改变。

    看到网上说 js 只有一个线程

    那么我理解 js 同时只能做一件事

    如果这个线程 同步去请求一个图片, 如果网络很卡, 那么其他地方就会卡住, 因为没有线程去处理其他地方

    可是我看到网上说, 用来异步就可以解决这个问题

    我的理解是: 用了异步后, 发起请求后,这个线程继续处理 ui,处理其他事情 , 等 io 请求返回结果以后,线程就切换到原来的地方,对 io 结果进行处理

    可是,js 怎么知道 io 请求完毕 了呢? 难道不用起一个新线程,专门请求 io 吗? 或者监听 io 请求状态吗

    谁告诉 js 这个 io 请求完毕了呢? 操作系统吗? 或者 其他的

    谢谢

    7 条回复    2020-04-30 15:55:48 +08:00
    754181906aaa
        1
    754181906aaa  
       2020-04-30 14:47:00 +08:00   1
    js 的单线程是对开发者而言的,就是你的代码运行在单线程上, 但是浏览器并不是单线程, 像 v8, 磁盘 io 就是用的线程池, 网络 io 是 epoll 。
    shintendo
        2
    shintendo  
       2020-04-30 14:48:16 +08:00   1
    js 调用浏览器的 api 发送请求,具体的发送和接收是浏览器的事情
    Mozshaw
        3
    Mozshaw  
       2020-04-30 14:56:37 +08:00   1
    这些是 Web API,io 请求完毕后会把回调放到 Task Queue 里。然后 JS 会通过 event loop 去循环的检测调用栈是否是空的,当调用栈空了之后就会从队列里取出回调,压入调用栈执行
    find456789
        4
    find456789  
    OP
       2020-04-30 15:47:26 +08:00
    @Mozshaw
    @shintendo
    @754181906aaa

    ========

    谢谢

    我的新理解如下:

    当我用浏览器打开一个网页后, 浏览器引擎会把代码捋一捋,把代码里所有方法 放入 堆栈里,也就是 task Queue

    js 线程就像一个工人,

    而 task Queue 就是工作列表,

    工人开始工作后,就去 task Queue 领取一份工作,先领取上面的任务(先进后出, 后进先出,先安排的任务后做,后安排的任务先做)

    工人做完一份工作后,这个工作就从 task Queue 里删除了(从堆栈里弹出了)

    然后工人继续领取下一份工作

    其中有一份工作是,发起一个异步 io 操作,工人领取了,并执行了这个 api,工人完成了发起请求的工作,于是继续领取下一份工作

    工人执行的那个 api 就是让浏览器去请求数据,这时候浏览器就去请求数据,

    在浏览器请求数据的过程中, 工人还是继续领任务、做任务,每做完一个任务,浏览器就会把这个任务从 task Queue 里删掉


    一段时间后(可能几十毫秒),浏览器得到了 io 数据,然后把 io 数据,和处理 io 数据的代码放在 task Queue 列表的最上面, 等待工人下一次来领取这个任务

    后来,工人做完了手上的工作,又来领取新工作, 就领取到了这个 带有 io 数据的任务, 然后 工人就按照代码对这个 io 数据进行处理、加工


    请问我的理解对吗
    m0cha
        5
    m0cha  
       2020-04-30 15:54:02 +08:00 via iPhone   1
    @find456789 这学期刚上了这门课,这理解是对的,所谓的 nodejs 单线程就是指,这个工人领任务和做任务是单线程的,至于浏览器 wjiqio 是由另外的线程完成的
    m0cha
        6
    m0cha  
       2020-04-30 15:54:24 +08:00 via iPhone   1
    @m0cha 浏览器完成 io
    fengfuliu
        7
    fengfuliu  
       2020-04-30 15:55:48 +08:00   2
    在执行代码过程中,如果遇到一些异步代码(比如 setTimeout,ajax,promise.then 以及用户点击等操作),那么浏览器就会将这些代码放到另一个线程(在这里我们叫做幕后线程,这个线程可能存在于浏览器或 js 引擎内,与主线程是分开的,处理文件读取、网络请求等异步事件。)中去执行,在前端由浏览器底层执行,在 node 端由 libuv 执行,这个线程的执行不阻塞主线程的执行,主线程继续执行栈中剩余的代码。
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     861 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 26ms UTC 21:42 PVG 05:42 LAX 14:42 JFK 17:42
    Do have faith in what you're doing.
    ubao snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86