V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
wesleypursuit
V2EX  ›  前端开发

Promise-大白话之[按需学习]

  •  
  •   wesleypursuit · 2017-11-12 14:29:36 +08:00 · 1594 次点击
    这是一个创建于 2351 天前的主题,其中的信息可能已经有所发展或是发生改变。

    背景

    之前就有在 GitHub 上吹过一个牛: https://github.com/eternityspring/ispider 打算做一个爬虫,爬点东西。但是一直一拖再拖。最近离职在找工作。时间大把。这就开始折腾起来了。目前在做的是构建自己的代理池。 简单来说,我需要去访问提供免费代理的网站,然后把这些免费的代理信息验证后入库。 假设我现在访问 A 页面,里边有 m 条代理数据。那么我还需要利用这 m 条代理信息去访问百度或者其他网站验证这个代理是否可用,可用则代理信息入库,否则丢掉。但是利用代理去访问百度是个异步的过程。我在什么时候知道这 m 条请求都完成了呢? 我想到的一种方法:定义 m 个变量初始值设置为 0,异步请求成功后吧变量赋值为 1,然后每个请求完成计算一下这 m 个变量的乘积。得到 1 则代表所有的请求都已完成。可是这种方法是不是麻烦了点。早就听闻 promise 是 es6 的新花样,可以解决这种多重回调的问题。于是就上 MDN 上文档撸起来。

    Promise

    MDN 上说:Promise 对象用于一个异步操作的最终完成(或失败)及其结果值的表示。(简单点说就是处理异步请求。我们经常会做些承诺,如果我赢了你就嫁给我,如果输了我就嫁给你之类的诺言。这就是 promise 的中文含义:诺言,一个成功,一个失败。) 呵呵,文绉绉的。还是上代码:

    // Promise 接受两个参数
    // resolve: 异步事件成功时调用(表白成功)
    // reject: 异步事件失败时调用(表白失败)
    var Tom = new Promise((resolve, reject) => {
    	// 获取表白结果
    	if (表白().result === '表白成功') {
    	    // 反馈
    	    resolve(表白().girlName)
        }
    	else {
    	    reject('小伙伴们,我 Tom 表白被拒了')
    	}
    })
    // 随机一个随机表白方法,返回表白结果和表白对象
    function 表白() {
        return {
            girlName:Math.random() > 0.5 ? '小红' : '花花',
            result:Math.random() > 0.5 ? '表白成功' : '表白被拒'
        }
    }
    // 表白完毕和小伙伴们分享表白结果
    Tom.then(res=> console.log('小伙伴们,我表白'+ res +'成功了') )  // 分享表白成功
       .catch(res=> console.log(res) )                            // 分享表白失败
    // 听 Tom 说打算表白,Jim 也要表白
    var Jim = new Promise((resolve, reject) => {
    	// 获取表白结果
    	if (表白().result === '表白成功') {
    	    // 反馈
    	    resolve(表白().girlName)
        }
    	else {
    	    reject('小伙伴们,我 Jim 表白被拒了')
    	}
    })
    Jim.then(res=> console.log('小伙伴们,我表白'+ res +'成功了') )  // 分享表白成功
       .catch(res=> console.log(res) )                            // 分享表白失败
    // 那么问题来了,我们怎么知道 Tom 还 Jim 都表白成功了,然后开一个 party 庆祝一下呢
    Promise.all([Tom,Jim])
           .then(res=> console.log(res))      // [Tom 表白对象,Jim 表白对象]
           .catch(res=> console.log(res));    // 第一个表白失败的对象
    

    看到这里是不是大概已经知道 promise 是个什么玩意了。 接着在我们的爬虫项目里边应用了:

    var proxyList= [{},{},{},{},{}];  // 一个空对象代表一个代理信息
    var promiseList = [];
    for(let i = 1;i<proxyList.length;i++){
      let promiseItem = new Promise((resolve,reject)=>{
        // 这里我们利用 setTimeout 来模拟异步请求验证 proxy 的可用性
        setTimeout(()=>{
            Math.random() > 0.001 ? resolve() : reject()
        })
      });
      promiseList.push(promiseItem);
    }
    Promise.all(promiseList).then(res=> console.log('验证完毕,可以下一页了'))
    

    到此,promise 的实际应用就算告一段落了。

    总结

    刚好最近在找工作,如果有被问到 promise 感觉又多了一个装逼的姿势了。 简历投了好多,面试好少啊...


    求坑位: https://eternityspring.github.io/

    1 条回复    2017-11-12 16:02:18 +08:00
    ashong
        1
    ashong  
       2017-11-12 16:02:18 +08:00 via iPhone
    前段时间把一个桌面工具界面完全 css+js 化,大量用到 promise 以实现所谓同步,逻辑嵌套之多有时候会把自己搞晕
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   2641 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 26ms · UTC 10:56 · PVG 18:56 · LAX 03:56 · JFK 06:56
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.