zoukankan      html  css  js  c++  java
  • ES6 Promise基础

    Promise

    异步编程

    • 回调函数实现
    • 事件监听
    • 发布订阅
    • Promise/A+和生成器函数
    • asynv/await

    回调函数

    回调的特点是error first,调用回调函数的时候第一个参数永远是错误对象,错误对象也是优先需要进行判断的

    const fs = require('fs')
    fs.readFile('./1.txt', 'utf8', function(err, data){
        if(err){
            console.log(err);
        }else{
            console.log(data);
        }
    })
    
    回调函数的问题
    • 无法捕获错误 try catch
    • 不能return,执行和回调是两个不同的执行栈
    • 回调地狱

    这种恶魔金字塔有以下问题:

    • 非常难看
    • 非常难以维护
    • 效率比较低,因为他们是串行的
    fs.readFile('./template.txt', 'utf8', function(err, data){
      fs.readFile('./data.txt', 'utf8', function(err, data){
        fs.readFile('./data.txt', 'utf8', function(err, data){
      
            })
        })
    })
    

    事件发布订阅实现

    • 通过事件发布订阅来实现
    const  EventEmitter = require('events');
    let eve = new EventEmitter();
    let html = {}; // temmplate data
    eve.on('ready', function(key, value){
        html[key] = value;
        if(object.keys(html).length == 2){
            console.log(html
        }
    })
    fs.readFile('./template.txt', 'utf8', function(err, data){
        eve.emit('ready', 'template', template);
    })
    fs.readFile('./1.data', 'utf8', function(err, data){
        eve.emit('ready', 'data', data);
    })
    

    生成器generator

    生成器是一个函数,可以用来生成迭代器
    生成器函数和普通函数不一样,普通函数是一旦调用一定会执行完
    但是生成器函数中间可以暂停,可以执行一会休一会

    生成器有一个特点,需要加个*
    生成器有若干个阶段, 使用yield区分

    function *go(){
        console.log(1);
        let b = yield 'a';
        console.log(2);
        let c = yield 'b'
        console.log(3);
        return c;
    }
    

    生成器函数和普通函数不一样,调用它的话函数并不会立刻执行
    它会返回此生成器的迭代器,迭代器是一个对象,每调用一次next就可以返回一个值对象,此对象有两个属性,一个是value就是yield后面那个值,一个是done表示是否迭代完成

    let it = go()
    let r1 = it.next();
    console.log(r1); // {value: 'a' , done: false}
    let r2 = it.next('B');
    console.log(r2); // { value:'B' , done: false}
    

    next第一次执行不需要参数,传参数是没有意义。参数会赋值给yield前面的变量

    let b = yield 'a'
    这一行实现输入和输出,本次的输出放在yield后面,下次的输入放在yield前面

    Promise

    let p = new Promise(function(resolve, reject){
        setTimeout(function(){
            let num = Math.random();
            if(num < .5){
                resolve(num);
            } else {
                reject('失败')
            }
        })
    });
    p1.then(function(data){
        console.log(data)
    }, function(err){
        console.log(err)
    });
    
    链式操作用法
    function runAsync1(){
        var p = new Promise(function(resolve, reject{
            setTimeout(function(){
                console.log('异步任务1执行完成');
                resolve('随便什么数据1')
            }, 1000)
        }))
        return p
    }
    
    function runAsync2(){
        var p = new Promise(function(resolve, reject{
            setTimeout(function(){
                console.log('异步任务2执行完成');
                resolve('随便什么数据2')
            }, 2000)
        }))
        return p
    }
    
    function runAsync3(){
        var p = new Promise(function(resolve, reject{
            setTimeout(function(){
                console.log('异步任务3执行完成');
                resolve('随便什么数据3')
            }, 3000)
        }))
        return p
    }
    
    runAsync1()
    .then(function(data){
        console.log(data);
        return runAsync2();
    })
    .then(function(data){
        console.log(data);
        return runAsync3();
    })
    .then(function(data){
        console.log(data);
    });
    

    异步任务1执行完成
    随便什么数据1
    异步任务2执行完成
    随便什么数据2
    异步任务3执行完成
    随便什么数据3

    或者直接return 数据

    runAsync1()
    .then(function(data){
        console.log(data);
        return runAsync2();
    })
    .then(function(data){
        console.log(data);
        return '直接返回数据';  //这里直接返回数据})
    .then(function(data){
        console.log(data);
    });
    

    异步任务1执行完成
    随便什么数据1
    异步任务2执行完成
    随便什么数据2
    直接返回数据

    reject用法

    reject的作用就是把Promise的状态置为rejected,这样我们在then中就能捕捉到,然后执行“失败”情况的回调

    function getNumber(){
        var p = new Promise(function(resolve, reject){
            //做一些异步操作
            setTimeout(function(){
                var num = Math.ceil(Math.random()*10); //生成1-10的随机数
                if(num<=5){
                    resolve(num);
                }
                else{
                    reject('数字太大了');
                }
            }, 2000);
        });
        return p;            
    }
    
    getNumber()
    .then(
        function(data){
            console.log('resolved');
            console.log(data);
        }, 
        function(reason, data){
            console.log('rejected');
            console.log(reason);
        }
    );
    

    1 或者 数字太大了

    catch用法
    getNumber()
    .then(function(data){
        console.log('resolved');
        console.log(data);
        console.log(somedata); //此处的somedata未定义})
    .catch(function(reason){
        console.log('rejected');
        console.log(reason);
    });
    

    如果执行的时候发生异常,就中止代码执行,将异常传递给catch的回调函数处理

    Promise.all

    Promise.all:会接受一个promise数组,如果promise全部完成了这个promise才会成功,如果有一个失败,那么这个promise就整个失败了

    Promise.race

    Promise.race 会接受一个promise数组, 只要一个成功,则就成功了,只要一个失败就失败了

  • 相关阅读:
    P4781 【模板】拉格朗日插值
    P1306 斐波那契公约数
    P1154 奶牛分厩
    P1028 数的计算
    P1445 [Violet]樱花
    2020 Multi-University Training Contest 4
    Codeforces Round #658 (Div. 2) D
    2020牛客暑期多校训练营(第八场) K
    Codeforces Round #659 (Div. 2)
    #10106. 「一本通 3.7 例 2」单词游戏
  • 原文地址:https://www.cnblogs.com/xiaoxu-xmy/p/13691908.html
Copyright © 2011-2022 走看看