首页   注册   登录
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐关注
Meteor
JSLint - a JavaScript code quality tool
jsFiddle
D3.js
WebStorm
推荐书目
JavaScript 权威指南第 5 版
Closure: The Definitive Guide
V2EX  ›  JavaScript

如果你自认熟悉 Promise,来猜一下这个代码的运行结果

  •  
  •   autoxbc · 91 天前 · 3295 次点击
    这是一个创建于 91 天前的主题,其中的信息可能已经有所发展或是发生改变。
    const onResolved = e => console.log('resolve , ', e );
    const onRejected = e => console.log('reject , ', e );
    
    new Promise( ( resolve , reject ) => {
    	resolve( new Promise( ( resolve , reject ) => {
    		resolve(42);
    	} ) );
    } ).then( onResolved , onRejected );
    
    new Promise( ( resolve , reject ) => {
    	resolve( new Promise( ( resolve , reject ) => {
    		reject(42);
    	} ) );
    } ).then( onResolved , onRejected );
    
    new Promise( ( resolve , reject ) => {
    	reject( new Promise( ( resolve , reject ) => {
    		resolve(42);
    	} ) );
    } ).then( onResolved , onRejected );
    
    new Promise( ( resolve , reject ) => {
    	reject( new Promise( ( resolve , reject ) => {
    		reject(42);
    	} ) );
    } ).then( onResolved , onRejected );
    

    如果猜错了,说明之前看的 Promise 教程都不合格,我还没见过合格的

    第 1 条附言  ·  90 天前

    继续关注这个帖子的朋友,送上一道附加题

    const onResolved = e => console.log(e);
    
    new Promise( ( resolve , reject ) => {
    	resolve( new Promise( ( resolve , reject ) => {
    		resolve(42);
    	} ) );
    } ).then(onResolved);
    
    new Promise( ( resolve , reject ) => {
    	resolve( Promise.resolve(43) );
    } ).then(onResolved);
    
    Promise.resolve( new Promise( ( resolve , reject ) => {
    	resolve(44);
    } ) ).then(onResolved);
    
    Promise.resolve( Promise.resolve(45) ).then(onResolved);
    
    33 回复  |  直到 2019-08-01 13:42:10 +08:00
        1
    jiangzhuo   91 天前
    这有点难度……我觉得就算教程合格了,也不一定能答对,至少需要个草稿纸……

    应该很多人挨个运行能答出来,比如
    resolve , 42
    reject , 42
    reject , 一个 Promise
    reject,一个 Promise 并且里面那个的 reject 没有 handle

    我觉得能答成这样就算及格了。真要把四个 promise 一起,你还得给人家其他条件才能算出正确结果了,意义不大……
        2
    binux   91 天前
    这个是大家来找茬吗?
        3
    autoxbc   91 天前
    @jiangzhuo #1 一个一个答对也算合格。不过我看过的教程,都没有清晰的解释 new Promise() 的行为,使得很多人说不出四段代码的关键区别
        4
    qdwang   91 天前 via iPhone
    还真从来没在实际中用过 reject 一个 promise。能说说哪种情况下需要这么写吗
        5
    zjsxwc   91 天前 via Android
    这个是最基本都 promise 用法啊,
    楼主这里相对正常使用时,奇葩一点的是被 resolve 和 reject 了一个 promise,
    当然是在 resolve 和 reject 之前执行这个 promise 里面的代码呗。
        6
    iceheart   91 天前 via Android
    UnhandledPromiseRejectionWarning:
    ??
        7
    jaskle   91 天前 via Android
    我决定放进 node 跑一下
        8
    jinliming2   91 天前   ♥ 10
    promise 的 resolve 是递归的,只要 resolve 一个 promise,就会继续等待这个 promise。
    而 reject 碰到就直接返回,如果 reject 的是一个 promise,这个 promise 不会被等待。
    所以:
    第一个 外层 promise 里 resolve 了一个 ( resolve 的 promise ),所以 then 的结果会递归等待里面的 promise 返回,里面的 promise resolve 了一个 42,所以得到了 “ resolve 的 42 ”。
    第二个 外层 promise 里 resolve 了一个 ( reject 的 promise ),所以 then 的结果会递归等待里面的 promise 返回,里面的 promise reject 了一个 42,碰到 reject 直接返回,被 then 的第二个参数抓到,所以得到了 “ reject 的 42 ”。
    第三个和第四个 外层 promise 直接 reject 了一个 promise (不管这个 promise 具体是啥),所以直接返回,被 then 的第二个参数抓到,所以得到 “ reject 的 promise<xxx>”。
    其中第三个因为内层 promise 是 resolve 的 42,所以结果是 “ reject 的 promise<resolve 42>”。
    而第四个因为内层 promise 是 reject 的 42,外层 promise 被 then 的第二个参数抓住了,但内层的没有,所以结果是 “ reject 的 promise<reject 42> 并带有一个未捕获的来自内部 promise 的异常”。

    不管你这个 promise 写多少层,resolve 都会递归下去,一旦碰到 reject 立即返回。
        9
    jinliming2   91 天前   ♥ 1
    所以:
    const a = async () => {
    xxxxx;
    return promise;
    };
    await a();
    如果 xxxxx 里没用到 await 语句,最后 return 了一个 promise,那么 a 的 async 标志可以去掉,变成一个普通函数。因为加上 async 标志,相当于是 resolve 了两次,而去掉就相当于变成 resolve 一次。(最后调用的时候依然得 await,像这样:)

    const a = () => {
    xxxxx;
    return promise;
    };
    await a();
        10
    Sparetire   91 天前 via Android
    关键是 reject 不会递归地 resolve 里面的 Promise 吧,猜测那就应该是先 reject 了后面两个并打印了两个 pending 的 Promise,然后再是 resolve 42 和 reject 42
        11
    zqx   91 天前 via Android
    如果楼主没见过合格的教程,你怎么知道你的结果就是唯一正确的呢?
        12
    Snail233   91 天前
    马克下,后面看
        13
    temporary   91 天前
        14
    mcfog   91 天前 via Android
    这种考察是否 promise 熟悉的方式我认为不合格
        15
    nikandaoleshenme   91 天前
    额,表示这样的代码看都不想看,难道是真香定律 [狗头]
        16
    daishankeke   91 天前   ♥ 1
    reject,promise 对象( resolved )
    reject,promise 对象( rejected )
    resolve,42
    reject,42

    我的理解:

    有一个 Promise 对象我们称他为 p1
    p1 在执行 resolve 时有一个参数 result,reject 执行时有一个参数 reason
    先来看 resolve:
    p1 的 resolve 方法被执行时,如果发现 result 是一个 Promise 对象就会这样处理:
    result.then(resolve, reject)
    其实是将自己的 resolve、reject 方法移交给 result,等待 result 去 resolve 之后,才会执行 p1 的 resolve,然后 p1 在 resolve 时才会执行 p1.then 里边的 onFulfilled 和 onReject 方法。
    再看 reject 的情况
    reject 方法不会检测 reject 时传入的 reason 是否是一个 Promise 对象,而是直接开启一个微任务清空 reject 的回调队列,同时将返回值 reason 传入,由于没有将自己的 reject 和 resolve 方法移交给 reason 这一步,所以在这题中他们要比上面的两个 resolve(new Promise)快。

    简单说就是 resolve 会判断传进来的 result 参数是不是一个 Promise,是的话会移交自己的 resolve 和 reject 方法,reject 则不会。

    当然... 如果你想清晰的了解具体是怎么执行的,我建议去看看那些符合 PromiseA+规范的 Promise 实现

    😂这两天我正在看 Promise,如果有不对的请指出
        17
    caocong   91 天前
    Promise 内没有 resolve 是种错误的写法 会编译报错 就如上面第二个和第四个
    这里主要是 resolve 的问题 并不是直觉的返回了一个 promise 对象
    文档里说的很清楚了 https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/resolve

    The Promise.resolve() method returns a Promise object that is resolved with a given value. If the value is a promise, that promise is returned; if the value is a thenable (i.e. has a "then" method), the returned promise will "follow" that thenable, adopting its eventual state; otherwise the returned promise will be fulfilled with the value. This function flattens nested layers of promise-like objects (e.g. a promise that resolves to a promise that resolves to something) into a single layer.

    所以看啥教程 直接读文档不就好了
        18
    mcfog   91 天前 via Android   ♥ 3
    @jinliming2 你可以仔细看下 https://promisesaplus.com/ 这里有几个要点:1. new Promise 的行为并没有被标准化,2. promise 和 thenable 的处理是不一样的 3. 实践中一个 promise 实现却很难探测出 promise 和 thenable 的区别 4. 标准中的 onRejected 是有递归展开行为的

    补充我自己的回复,楼主的出题基本聚焦于不在标准中的,而且实战中属于需要避免的写法,所以不是一个好的题目,类似 i++ + ++i
        19
    hoyixi   91 天前
    其实很简单,记得早就说过了,Promise/await/async 这些都是 js 对异步回调的语法糖,根本不是啥高深玩意,你越往深里想,越是把简单的事情想复杂。

    Promise 的 resolve,一定会逐层 resolve,为啥,就好比你 callback 里又有 callback,不 callback 到最后,根本不知道结果;

    Promise 的 reject,直接返回 reject 的值, 为啥,就好比你最外层 callback 直接错误,还往里层走个屁。


    别钻牛角尖,扣学术字眼。就那么简单。就一个语法糖,写起来、维护起来舒服而已,漫天的教程,都在扯淡。
        20
    beginor   91 天前 via Android
    既然有了 promise,还是配合 async/await 食用, 疗效更佳
        21
    PyCode   91 天前
    所以有没有合格的教程?
        22
    banricho   91 天前
    这……无论是面试题还是业务代码都是不合格的 = =
    都什么年代了。。。
        23
    will0404   91 天前   ♥ 1
    有了 async/await 再去折腾这个没必要了,即使没有 async/await,没有任何场景会需要这样写代码。
        24
    ochatokori   91 天前 via Android
    js 考题日常
    为了整人出题…
        25
    libo930920   91 天前
    仔细看过 Promise A+规范的,基本都应该能答出来的吧
        26
    abcdGJJ   91 天前
    @temporary node 10.7 上是一致的 node 10 好像改过 promise
        27
    azh7138m   91 天前
    @zqx 标准是唯一且正确的,可以看标准。
    教程不过是一个演绎(有的连演绎都算不上),可以选择不看。
        28
    Raymon111111   91 天前
    那 js 里
    [ + { = ?
    ] + } 呢?
        29
    zqx   91 天前 via Android
    @azh7138m 标准也是教程
        30
    azh7138m   91 天前
    @zqx 那你应该是没看过标准,standard 和 tutorial 可完全不是一个东西
        31
    autoxbc   91 天前
    @qdwang #4 这确实不是种模式用法,但也称不上反模式,算是知识盲点吧
        32
    zqx   90 天前 via Android
    @azh7138m 有意思,公开的东西想看就看没什么门槛,好像比别人高级?
        33
    libook   83 天前
    这个知识很有趣,但对教程的全盘否定有些太偏激了。
    关于   ·   FAQ   ·   API   ·   我们的愿景   ·   广告投放   ·   感谢   ·   实用小工具   ·   1320 人在线   最高记录 5043   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.3 · 26ms · UTC 17:41 · PVG 01:41 · LAX 10:41 · JFK 13:41
    ♥ Do have faith in what you're doing.