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数组, 只要一个成功,则就成功了,只要一个失败就失败了

原文地址:https://www.cnblogs.com/xiaoxu-xmy/p/13691908.html