zoukankan      html  css  js  c++  java
  • ES6之promise

    Promise对象用于表示一个异步操作的最终状态(完成或失败)以及其返回的值。---MDN

    同步任务会阻塞程序执行(alert、for、...)。

    异步任务不会阻塞程序执行(setTimeout、fs.readFile、....)。

    promise对象放的是我们未来要做的事情,当我们实例化这个对象后,就开始做这个事。成功做成功的事,失败做失败的事。之前解决异步主要方式是通过回调函数,事件。

    使用Promise(then、catch、finally)

    Promise.all & Promise.race

    Promise.resolve & Promise.reject

    // 比较传统的回调方式与promise
    
    // -------------------------------------------------------
    // 回调
    
    // 方法 用于请求数据(模拟)
    // function f(cb) {
    //     setTimeout(function() {
    //         cb && cb();//短路操作,与,前面的对了,执行后面的操作。
    //     }, 1000);
    // }
    
    // f(function() {
    //     console.log(1);
    
    //     f(function() {
    //         console.log(2);
    
    //         f(function() {
    //             console.log(3);
    
    //             f(function() {
    //                 console.log(4);
    
    //                 f(function() {
    //                     console.log(5);
    
    //                     f(function() {
    //                         console.log(6);
    //                     });
    //                 });
    //             });
    //         });
    //     });
    // });
    
    // -------------------------------------------------------
    // promise
    
    // 方法 用于请求数据(模拟)
    function f() {
        return new Promise(resolve => {
            setTimeout(function() {
                resolve();
            }, 1000);
        })
    }
    
    f()
        .then(function() {
            console.log(1);
            return f();//注意这里返回的是新的promise对象,而不是第一个生成的。
        })
        .then(function() {
            console.log(2);
            return f();
        })
        .then(function() {
            console.log(4);
            return f();
        })
        .then(function() {
            console.log(3);
            return f();
        })
        .then(function() {
            console.log(5);
            return f();
        })
        .then(function() {
            console.log(6);
        });

    注意:Promise 新建后立即执行,所以首先输出的是Promise,然后,then方法指定的回调函数,将在当前脚本所有同步任务执行完才会执行。

    // 信任问题
    
    // 第三方的某个库
    function method(cb) {
      // 未按所想的预期执行回调
      setTimeout(function() {
        // 讲道理应该是现在该调用回调了
        cb && cb();
        // 但是?? 好像这个库有bug啊 emm 被多调用了一次
        cb && cb();
      }, 1000);
    }
    
    // promise一但被确定为成功或者失败 就不能再被更改
    
    function method() {
      return new Promise(resolve => {
        setTimeout(function() {
          // 成功
          resolve();
          resolve();
        }, 1000);
      });
    }
    
    
    // 控制反转
    
    function method(cb) {
      // 未按所想的预期执行回调
      setTimeout(function() {
        // 执行回调 但是添油加醋
        cb && cb.call({a: 1, b: 2});
      }, 1000);
    }
    
    function method(cb) {
      return new Promise(resolve => {
        setTimeout(() => {
          resolve(); // 调用的resolve全为自己所写书写的流程 很大程度上改善了反转控制的问题
        }, 1000);
      });
    }

    错误处理:

    function f(val) {
      return new Promise((resolve, reject) => {
        if (val) {
          resolve({ name: '小明' });//只能传递一个参数,第二个取不到。
        } else {
          reject('404');
        }
      }); 
    }
    
    // then(resolve, reject)
    // then方法中的第二个回调 失败时候做的事
    
    // f(false)
    //   .then((data) => {
    //     console.log(data)
    //   }, e => {
    //     console.log(e);
    //   })
    
    //----------------------------------------
    // catch
    // 使用实例的catch方法 可以捕获错误
    
    // f(true)
    //   .then(data => {
    //     console.log(data);
    //     return f(false);
    //   })
    //   .then(() => {//若是错误没有被处理,则中间的代码都不会执行,除非有对错误进行处理。
    //     console.log('我永远不会被输出');
    //   })
    //   .then(() => {
    
    //   })
    //   .catch(e => {
    //     console.log(e);
    //     return f(false) ;
    //   });
    
    //----------------------------------------
    // finally
    // 不论成功还是失败 finally中的内容一定会执行
    
    f(true)
      .then(data => {
        console.log(data);
        return f(false);
      })
      .catch(e => {
        console.log(e);
        return f(false);
      })
      .finally(() => {
        console.log(100);
      });

    注意:Promise构造函数接受一个函数作为参数,该函数的两个参数分别是resolve和reject,它们是两个函数then方法可以接受两个回调函数作为参数,第一个回调函数是Promise对象的状态变为resolved时调用,第二个回调函数是Promise对象的状态变为rejected时调用,其中,第二个函数是可选的,不一定要提供,Promise.prototype.catch方法是.then(null, rejection)的别名,用于指定发生错误时的回调函数。

    Pormise有三种状态:pending进行中,fulfilled成功,rejected失败。状态的改变只有两种,

    从pending--》fulfilled,从pending--》rejected。状态的改变不可逆,一旦决议不能再修改。

    (1)对象的状态不受外界影响,Promise对象代表一个异步操作,有三种状态:pending(进行中)、fulfilled(已成功)和rejected(已失败),只有异步操作的结果,可以决定当前是哪一种状态,任何其他操作都无法改变这个状态,这也是Promise这个名字的由来,它的英语意思就是“承诺”,表示其他手段无法改变。

    (2)一旦状态改变,就不会再变,任何时候都可以得到这个结果,Promise对象的状态改变,只有两种可能:从pending变为fulfilled和从pending变为rejected,只要这两种情况发生,状态就凝固了,不会再变了,会一直保持这个结果,这时就称为 resolved(已定型),如果改变已经发生了,你再对Promise对象添加回调函数,也会立即得到这个结果,这与事件(Event)完全不同,事件的特点是,如果你错过了它,再去监听,是得不到结果的。

    // Promise.all方法可以把多个promise实例 包装成一个新的promise实例
    // Promise.all([ promise1, promise2 ]) : Promise//接收一个数组,数组中的值为promise对象
    //若是存在失败的promise,则判断为失败,全部成功才为成功。
    //默认会将参数用promise.resolve()包一下。
    // 模拟需要多个请求的数据 才能进行下一步操作的情况 // function getData1() { // return new Promise((resolve, reject) => { // setTimeout(() => { // console.log('第一条数据加载成功'); // resolve('data1'); // }, 1000); // }); // } // function getData2() { // return new Promise((resolve, reject) => { // setTimeout(() => { // console.log('第二条数据加载成功'); // resolve('data2'); // }, 1000); // }); // } // function getData3() { // return new Promise((resolve, reject) => { // setTimeout(() => { // console.log('第三条数据加载成功'); // resolve('data3'); // }, 1000); // }); // } // function getData4() { // return new Promise((resolve, reject) => { // setTimeout(() => { // // console.log('第四条数据加载成功'); // reject('data4 err'); // }, 500); // }); // } // let p = Promise.all([]);//传入空数组,决议会成功 // p.then(() => { // console.log('dfsafd'); // }, e => { // console.log(e); // }); // 不是用Promise.all // let count = 0; // let err = false; // function func() { // if (count < 4) return; // if (err) { // // .... // } // console.log('全部拿到了 !'); // } // function getData1() { // setTimeout(() => { // console.log('第一条数据加载成功'); // count ++; // func(); // }, 1000); // } // function getData2() { // setTimeout(() => { // console.log('第二条数据加载成功'); // count ++; // func(); // }, 1000); // } // function getData3() { // setTimeout(() => { // console.log('第三条数据加载成功'); // count ++; // func(); // }, 1000); // } // function getData4() { // setTimeout(() => { // console.log('第四条数据加载成功'); // count ++; // func(); // }, 1000); // } // getData1(); // getData2(); // getData3(); // getData4();

     promise.race();//和all不同的地方在于,一旦有一个promise实例成功或者失败了,那该方法马上返回promise实例就为成功或者失败。传入空数组时,什么反应都没有。其他与promise.all()方法相同。

    // Promise.resolve() 和 Promise.reject()
    // 常用来生成已经被决议为失败或者成功的promise实例
    
    // Promise.resolve
    // ---------------------------------------
    // 传递一个普通的值
    // let p1 = new Promise(resolve => {
    //   resolve('成功!');
    // });
    
    // let p2 = Promise.resolve('成功!');
    //以上两种方法等价。返回的是promise实例对象。
    // // ---------------------------------------
    // // 传递一个promise实例
    // let poruomiesi = new Promise(resolve => {
    //   resolve('耶!')
    // });
    
    // // 直接返回传递进去的promise
    // let p = Promise.resolve(poruomiesi);
    
    // p.then(data => void console.log(data));
    
    // console.log(p === poruomiesi); //true
    
    // // ---------------------------------------
    // // 传递一个thenable
    // // 如果传递的是个thenable,则会把他包装成promise对象并立即执行该对象的then方法。//概念和类数组和数组的关系有点类似,鸭子类型。
    // let obj = {
    //   then(cb) {
    //     console.log('我被执行了');
    //     cb('哼!');
    //   },
    //   oth() {
    //     console.log('我被抛弃了');
    //   }
    // }
    
    // // 立即执行then方法
    // Promise.resolve(obj).then(data => {
    //   console.log(data);
    // });
    
    // // Promise.reject 
    
    // Promise.reject({ then() { console.log(1) } })
    //   .then(() => {
    //     console.log('我不会被执行');
    //   }, e => {
    //     console.log(e);
    //   });
    
    // console.log(1);
    
    // let p = new Promise(resolve => {
    //   console.log(2);
    //   resolve();
    //   console.log(3);
    // });
    
    // console.log(4);
    
    // p.then(() => {
    //   console.log(5);
    // });
    
    // console.log(6);
    
    
    // 把同步的任务转成异步任务
    
    function createAsyncTask(syncTask) {//自己封装的一个将同步任务转化成异步任务的函数
      return Promise.resolve(syncTask).then(syncTask => syncTask());
    }
    
    createAsyncTask(() => {
      console.log('我变成了异步任务!!!');
      return 1 + 1;
    }).then(res => {
      console.log(res);
    });
    
    console.log('我是同步任务!');

     小案例:

    // 页面中有个板块 需要多张图片加载完之后才能进行展示
    
    const loadImg = src => {
        return new Promise((resolve, reject) => {
            const img = new Image();
    
            img.src = src;
    
            img.onload = void resolve(img);
            img.onerror = void reject('加载失败');
        });
    };
    
    const imgs = [
        'https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1526734981&di=fe12efe9e3a76bd3bb5ac202a3c76823&imgtype=jpg&er=1&src=http%3A%2F%2Fd15.lxyes.com%2F15xm%2Fact%2F20151105%2F20%2F99112408.jpg',
        'https://ss1.bdstatic.com/70cFvXSh_Q1YnxGkpoWK1HF6hhy/it/u=1252816855,3131381110&fm=27&gp=0.jpg',
        'https://ss0.bdstatic.com/70cFvHSh_Q1YnxGkpoWK1HF6hhy/it/u=1906477750,651116720&fm=27&gp=0.jpg'
    ];
    
    Promise.all(imgs.map(src => loadImg(src))).then(arr => {
        console.log(arr);
    });
  • 相关阅读:
    修改NavigationBarItem的字体大小和颜色的使用方法
    iOS 大文件断点下载
    iOS 文件下载
    UITableView优化
    iOS 应用的生命周期
    iOS RunLoop简介
    iOS 线程间的通信 (GCD)
    iOS 多线程GCD的基本使用
    iOS 多线程GCD简介
    CSS--复习之旅(一)
  • 原文地址:https://www.cnblogs.com/zhonghonglin1997/p/10146858.html
Copyright © 2011-2022 走看看