看传统JS下的求婚历程模拟——引申:初步认识Promise

男神觉得时机成熟了,手捧99朵披着月季的玫瑰向女神求婚:

“小妞妞,嫁给我吧!我发誓,我会对你一辈子好的!”
“这个嘛,你先去问问我爸爸,我大伯以及我大姑的意思,他们全部都认可你,我再考虑考虑!对了,如果我爸没有答复,大伯他们肯定是不会同意的;如果大伯没有答复,大姑也是不会同意的。”

在传统的JS中,类似这种多嵌套,多异步,多发展的,我们需要牺牲(对于程序来讲)微不足道的时间换取代码的空间和易维护性。

因为得到长辈同意是需要等待的,而且一次只能攻略一个长辈,而且还能重复攻略。如果我们使用当下的JS去套用现实逻辑,可能就会这样子(无需细看):

男神.请求({
   姓名: "岳父",
   成功: 男神.继续请求({
       姓名: "大伯",
       成功: 男神.继续请求({
           姓名: "大姑",
           成功: 男神.最终请求({
               姓名: "女神",
               成功: "求婚成功",
               失败: "求婚失败"
            }),
            失败: 男神.继续请求({
               姓名: "大姑",
               成功: 男神.最终请求({
                   姓名: "女神",
                   成功: "求婚成功",
                   失败: "求婚失败"
                }),
                失败: "求婚失败"
            })
        }),
        失败: 男神.继续请求({
           姓名: "大伯",
           成功: 男神.继续请求({
               姓名: "大姑",
               成功: 男神.最终请求({
                   姓名: "女神",
                   成功: "求婚成功",
                   失败: "求婚失败"
                }),
                失败: 男神.继续请求({
                   姓名: "大姑",
                   成功: 男神.最终请求({
                       姓名: "女神",
                       成功: "求婚成功",
                       失败: "求婚失败"
                    }),
                    失败: "求婚失败"
                })
            }),
            失败: "求婚失败"
        })
    }),
    失败: 男神.请求({
       姓名: "岳父",
       成功: 男神.继续请求({
           姓名: "大伯",
           成功: 男神.继续请求({
               姓名: "大姑",
               成功: 男神.最终请求({
                   姓名: "女神",
                   成功: "求婚成功",
                   失败: "求婚失败"
                }),
                失败: 男神.继续请求({
                   姓名: "大姑",
                   成功: 男神.最终请求({
                       姓名: "女神",
                       成功: "求婚成功",
                       失败: "求婚失败"
                    }),
                    失败: "求婚失败"
                })
            }),
            失败: 男神.继续请求({
               姓名: "大伯",
               成功: 男神.继续请求({
                   姓名: "大姑",
                   成功: 男神.最终请求({
                       姓名: "女神",
                       成功: "求婚成功",
                       失败: "求婚失败"
                    }),
                    失败: 男神.继续请求({
                       姓名: "大姑",
                       成功: 男神.最终请求({
                           姓名: "女神",
                           成功: "求婚成功",
                           失败: "求婚失败"
                        }),
                        失败: "求婚失败"
                    })
                }),
                失败: "求婚失败"
            })
        }),
        失败: "求婚失败"
    })
})

为啥JS呈现的会这么复杂呢?

  1. 代码需要预先设定好未来要发生的事情(先知视角);但是现实世界并不会如此(经历者视角);
  2. 代码中,空间是稀缺资源;而现实世界中,时间才是。

所以,传统JS中,为了实现上面的嵌套,就需要这么做:

var Nanshen = {
    "身高": 180,
    "体重": 80,
    "年薪": "200k",
    request: function (obj) {
        if (Math.random() > 0.2) {                     // 假设男神每次攻略,成功的概率为0.8
            obj.success();
        } else {
            obj.error;
        }
    }
};
var Request = function (names, success) {     

       // names是一个数组,这里是["岳父", "大伯", "大姑"]

    var index = 0,
        first = 0;                                              // 每个亲戚有两次攻略机会
    var request = function () {
        if (names[index]) {
            Nanshen.request({
                name: name[index],
                success: function () {
                    first = 0;
                    console.log("成功拿下" + names[index]);
                    index++;
                    request();                                  // 如果成功,攻略下一个亲戚
                },
                error: function () {
                    if (first == 1) {
                        console.log("依旧没能拿下" + names[index]);  

           // 某亲戚两次攻略都失败,则求婚失败,退出求婚嵌套

                        return;
                    } else {
                        console.log("没能拿下" + names[index] + ",再试一次");
                    }
                    first = 1;
                    request();                                 // 如果成功,攻略下一个亲戚
                }
            });
        } else {
            success();
        }
    };
    request();
};

Request(["岳父", "大伯", "大姑"], function () {      // 传入参数:亲戚数组,调用上面的循环
    Nanshen.request({
        name: "女神",
        success: function () {
            console.log("女神同意,求婚成功!");
        },
        error: function () {
            console.log("女神不同意,求婚失败!");
        }
    });
});

想要用一种“先知”的角度去实现这个求婚历程,也就是实现现实世界中的思维:“搞定岳父→搞定大伯→搞定大姑→搞定女神”,请参考:https://www.zhangxinxu.com/wordpress/2014/02/es6-javascript-promise-%E6%84%9F%E6%80%A7%E8%AE%A4%E7%9F%A5/

Promise去实现我们的求婚过程也就是像下面这样:

// 男神的各项参数
var NanShen = {
    "身高": 180,
    "体重": 80,
    "年薪": "200K",
    request: function(obj) {
        // 成功与否随机决定
        // 执行成功的概率为80%
        if (Math.random() > 0.2) {
            obj.success();
        } else {
            obj.error();
        }
    }
};

var Request = function(name) {
  return new Promise(function(resolve,reject) {
    var failed = 0; request = function() {
      NanShen.request({
        name: name,

        success: function() {
          console.log(name + '攻略成功!');
          failed = 0;
          resolve();
        },

        error: function() {
          if(failed === 0) {
            console.log("第一次攻略" + name + "失败,重试一次!");
            failed === 1;
            // 重新攻略一次
            request();
          } else {
            console.log("依然没有拿下" + name + ",求婚失败!");
            reject();
          }
        }
      });
    };
    request();
  });
};


Rrequest("岳父")                                        // 搞定岳父,然后...
.then(function() { return Request("大伯"); })           // 搞定大伯,然后...
.then(function() { return Request("大姑"); })           // 搞定大姑,然后...
.then(function() {
  NanShen.request({
    name: "女神",
    success: function() {
      console.log("女神同意,求婚成功!");
    },
    error: function() {
      console.log("女神不同意,求婚失败!"):
    }
  });
});

哈,忘记demo了,您可以狠狠地点击这里:男神求婚历程的Promise实现 点击刷新测试你的人品吧!

看上去代码量和传统JS实现不分伯仲,但是注意下面这段代码:

当局者思维的代码呈现就是异步回调形式,先知思维的代码呈现就是Promise形式。

如果套用求婚的故事,则:

  • 先知思维(第三人称视角)——搞定岳父→搞定大伯→搞定大姑→搞定女神
  • 当局者思维(第一人称视角)——去搞定岳父→…等待期…结果来了…→去搞定大伯→…等待期…结果来了…→去搞定大姑→…等待期…结果来了…→去搞定女神→…等待期…结果来了…

前者是先知是上帝,在规划;后者是凡人,在经历。

还是那句话,Promise只是让我们当下的JS换了一种形式实现,更符合编程时候的思考角度与方式。因此,通过特定的转换,我们也可以让不支持Promise的低版本浏览器支持之。您可以试试在页面引入如下JS:

<script src="http://s3.amazonaws.com/es6-promises/promise-0.1.1.min.js"></script>

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值