看到一个面试题 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
1sm23
V2EX    Javascript

看到一个面试题

  •  
  •   1sm23 2021-03-01 18:27:22 +08:00 6001 次点击
    这是一个创建于 1689 天前的主题,其中的信息可能已经有所发展或是发生改变。
    函数在执行之后等待 3 秒返回 1,感觉是一个 js 事件的问题,想不出来
    第 1 条附言    2021-03-02 10:59:12 +08:00
    #19 那个能成,我就不贴出来了
    第 2 条附言    2021-03-02 14:14:12 +08:00
    审题!是 return 1
    settimeout 的别往下发了啊,settimeout 加到队列里,执行栈里的东西都跑完返回出来了
    45 条回复    2021-03-11 18:41:42 +08:00
    jatai
        1
    jatai  
       2021-03-01 18:32:54 +08:00 via Android
    ..... promise, setTimeout resolve
    leopod1995
        2
    leopod1995  
       2021-03-01 19:14:02 +08:00   1
    ```js
    (()=>{
    setTimeout(()=> {
    return 1;
    }, 1000 *3)
    })()

    ```
    irytu
        3
    irytu  
       2021-03-01 19:26:40 +08:00 via iPhone
    至少 setTimeout 应该想出来
    pkupyx
        4
    pkupyx  
       2021-03-01 21:16:07 +08:00
    想起来个题还稍微复杂点:

    testFunc() {
    console.log("要求这句话立即输出",new Date());
    setTimeout(()=>{console.log("要求这句话 3 秒后输出",new Date());},1);
    // todo:要求不改动上面代码,这行后面写一段代码完成上面的需求。

    }
    autoxbc
        5
    autoxbc  
       2021-03-01 22:55:25 +08:00   1
    @pkupyx #4 微任务阻塞宏任务?
    // todo
    const start = new Date();
    queueMicrotask( function callee(){
      if( new Date() - start < 3000 )
       queueMicrotask(callee);
    });
    murmur
        6
    murmur  
       2021-03-01 23:03:25 +08:00
    @pkupyx 修改 console.log 的函数算么
    Kasumi20
        7
    Kasumi20  
       2021-03-01 23:21:24 +08:00   1
    等待 3 秒后返回 1,一定是异步的,要么返回 Promise 要么延迟传递消息

    不可能同步地卡线程 3 秒

    接下来给出一个帅气的答案:
    async function sleepSync(n) { return new Promise(resolve => setTimeout(() => resolve(), n)); }

    async function task() {
    await sleepSync(3000);
    return 1;
    }
    ericls
        8
    ericls  
       2021-03-01 23:25:51 +08:00
    这个需要写一个函数把主线程 block 3 秒,可能可以使用一些数学运算和循环之类的

    否则在 Javascript 里面,很难 block 主线程
    ericls
        9
    ericls  
       2021-03-01 23:31:14 +08:00
    @Kasumi20 你这个返回的是 promise
    @leopod1995 你这个返回 undefined
    Biwood
        10
    Biwood  
       2021-03-01 23:42:41 +08:00
    @Kasumi20 #7
    我点了感谢,不过仔细想想好像也不符合题目描述,要求“返回 1”,严格来讲 async 函数返回的是 Promise 对象,而不是 1 。楼上说用 setTimeout 好像也不对,因为计时器的回调函数的返回值不是外层函数的返回值。这样看能只能用阻塞主线程,用 Date.now()计数 3 秒再返回。
    Biwood
        11
    Biwood  
       2021-03-01 23:44:14 +08:00
    function foo() {
    const start = Date.now();
    while (Date.now() - start < 3000) {}
    return 1;
    }
    Kasumi20
        12
    Kasumi20  
       2021-03-01 23:44:28 +08:00
    @ericls 敢在项目里动这种念头,你怕不是要被打屎
    ericls
        13
    ericls  
       2021-03-01 23:58:05 +08:00 via iPhone
    @Kasumi20 这个题你还能怎么解? 自己改一个 runtime?
    Kasumi20
        14
    Kasumi20  
       2021-03-02 00:01:29 +08:00   1
    @murmur #4

    这个可以根据变量提升原则来实现:

    console.log("要求这句话立即输出",new Date());
    setTimeout(()=>{console.log("要求这句话 3 秒后输出",new Date());},1);
    // todo:要求不改动上面代码,这行后面写一段代码完成上面的需求。

    function setTimeout(func) {
    globalThis.setTimeout(func, 3000);
    }
    1sm23
        15
    1sm23  
    OP
       2021-03-02 00:10:54 +08:00
    @leopod1995 #2 你这个一执行就返回 undefined 啦
    KMpAn8Obw1QhPoEP
        16
    KMpAn8Obw1QhPoEP  
       2021-03-02 00:13:49 +08:00 via Android
    @autoxbc 感觉这个靠谱
    gBurnX
        17
    gBurnX  
       2021-03-02 00:47:30 +08:00
    最科学的方法 ,应该是把函数调用,改为框架调用。这样你就可以在框架里,利用各种 promise 、setTimeout 了。甚至还可以加入查询进度的功能。

    简单来说,把
    A 调用函数 B,改为

    A 调用框架 B 。并且把调用过程,改为 2 个过程:
    1.A 调用框架 B,并且发送参数、处理函数与回调函数。
    2.框架 B 开始执行处理函数,执行完毕后,开发可以利用任何方法,延迟 3 秒。
    3.延迟 3 秒后,框架 B 执行回调函数来通知 A 。
    4.在 2 与 3 之间,甚至 A 还可以调用框架 B,来查询处理进度。
    akatquas
        18
    akatquas  
       2021-03-02 10:05:38 +08:00
    @leopod1995 你这返回值,被谁接住了? 谁能拿到这个返回的 1 ?
    cenbiq
        19
    cenbiq  
       2021-03-02 10:29:16 +08:00   5
    fun block(){
    var startAt = Date.now()
    while(true) {
    if (Date.now() - startAt >= 3000) {
    return 1;
    }
    }
    }
    zzh7982
        20
    zzh7982  
       2021-03-02 10:32:46 +08:00
    @cenbiq 同样的想法
    1sm23
        21
    1sm23  
    OP
       2021-03-02 10:59:57 +08:00
    @cenbiq 直呼牛逼
    cczeng
        22
    cczeng  
       2021-03-02 11:12:34 +08:00
    睡眠排序的兄弟?
    rodrick
        23
    rodrick  
       2021-03-02 11:24:07 +08:00
    昨天问了我怎么在代码里区分是 http1 还是 2,回来查了一下就找到一个 window.chrome.loadTimes().connectionInfo
    togou
        24
    togou  
       2021-03-02 12:28:23 +08:00
    return new Promise(r=>setTimeout(r(1),3000));
    zhuweiyou
        25
    zhuweiyou  
       2021-03-02 13:18:38 +08:00
    await new Promise(resolve => setTimeout(resolve, 3000))
    1sm23
        26
    1sm23  
    OP
       2021-03-02 13:57:23 +08:00
    @togou 不行,返回 Promise
    q673115816
        27
    q673115816  
       2021-03-02 14:56:54 +08:00
    await new Promise(resolve => setTimeout(resolve, 3000, 1))
    pkupyx
        28
    pkupyx  
       2021-03-02 15:45:17 +08:00
    卡死当前线程的都 OK,答案自己跑一下就试出来能不能过了,主要考察对 JS 线程与任务调度的理解。
    xutao881
        29
    xutao881  
       2021-03-02 15:52:48 +08:00
    。。。这个需求用来骗甲方好给自己留有优化的余地么?直接阻塞线程可还行
    shilyx
        30
    shilyx  
       2021-03-02 15:55:28 +08:00
    其实这个题在问:
    "既然你说你懂 JS,那么能否用 JS 证明你不懂 JS ?“
    cxe2v
        31
    cxe2v  
       2021-03-02 16:28:42 +08:00
    @autoxbc
    @enchilada2020
    这代码跑了,不靠谱
    autoxbc
        32
    autoxbc  
       2021-03-02 17:27:27 +08:00 via iPhone
    @cxe2v 那个代码是对 #4 题目的,不是楼主的题目
    cxe2v
        33
    cxe2v  
       2021-03-02 18:25:20 +08:00
    @autoxbc 我就是对的 4 楼的题目跑的啊,不会间隔三秒输出,我在浏览器控制台跑的
    autoxbc
        34
    autoxbc  
       2021-03-02 18:41:37 +08:00 via iPhone
    @cxe2v 那你再仔细检查一下吧,我在 firefox,vivaldi,node,deno 各跑了一次。另外为了排版,缩进那里有全角空格,要手工去掉
    libook
        35
    libook  
       2021-03-02 18:54:55 +08:00
    理论上来说,3 秒后返回 1,应该是需要阻塞线程的,否则只能立即返回 promise,然后 3 秒后接收到值。
    lwlizhe
        36
    lwlizhe  
       2021-03-02 19:22:25 +08:00
    好像 java 的类加载机制这块范例中有这种类似的,可惜这里是 js……
    djs
        37
    djs  
       2021-03-02 20:41:14 +08:00
    var fun = () => {
    var star = new Date().getTime();
    let t = new Date().getTime();
    while (t - star < 3000) {
    t = new Date().getTime();
    }
    return 1;
    };
    djs
        38
    djs  
       2021-03-02 20:41:42 +08:00
    @djs #37 我把线程阻塞掉 3s- -,不懂符不符合
    rrfeng
        39
    rrfeng  
       2021-03-02 20:53:14 +08:00
    谁给我解释一下,这不就是个 sleep(3s) 的问题吗?还是我理解错了?

    js 里没法实现 sleep 吗?
    autoxbc
        40
    autoxbc  
       2021-03-02 21:39:55 +08:00
    @rrfeng #39 js 可以 sleep,不过要用异步实现。异步的话原函数就需要先返回 promise,等 sleep 结束 resolve 出原始返回值

    而这里题目不允许修改函数返回值,也就不能异步,必须同步实现,只能用死循环阻塞住同步任务

    本质上不是问生产代码怎么写,而是加个不必要的预设,逼你用些奇技淫巧,目的是考察对任务调度的理解
    cxe2v
        41
    cxe2v  
       2021-03-02 22:09:31 +08:00
    @autoxbc 好了,我找到我的问题出在哪儿了
    dd112389
        42
    dd112389  
       2021-03-03 15:29:29 +08:00
    这个只能阻塞主线程来做吧, 异步基本都是在局部域里面, 拿不到返回值的.
    之前看过腾讯云的 cos sdk, 忘了是 v 几, 就是阻塞主线程等待对象初始化完毕.
    现在好像都改异步了.
    fy136649111
        43
    fy136649111  
       2021-03-03 16:02:44 +08:00
    还可以这样
    function sleep(){
    Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, 3000);
    }
    fy136649111
        44
    fy136649111  
       2021-03-03 16:04:14 +08:00
    @fy136649111 function sleep(){
    Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, 3000);
    return 1;
    }
    zeni123
        45
    zeni123  
       2021-03-11 18:41:42 +08:00
    @cenbiq 是让用户等待三秒然后返回 1 哈哈哈 真等待 任何东西都要等待 不含糊
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     5855 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 37ms UTC 02:42 PVG 10:42 LAX 19:42 JFK 22:42
    Do have faith in what you're doing.
    ubao msn 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