异步编程之Promise(一)

1、Js中常见的异步编程方式?

1)回调函数实现
2)发布订阅、通知
3)事件监听
4)Promise/A+ 和 生成器函数
5)async/await

1.2 回调函数

回调函数就是把任务拆解成两部分,把任务的第二部份单独写在一个函数里面,等到执行完其它任务重新执行这个任务的时候,就直接调用这个函数,从而达到异步效果

let cook = (step1, callback) => {    
    // 1. 煮牛肉
    console.log(`烧水煮${step1}`);    
    //  2. 放入土豆(5秒后执行)
    setTimeout(() => {        
        let step2 = '放入土豆';
        callback(step2);
    }, 5000)
};

// 1. 先煮牛肉  
cook('牛肉', (data) => {    
   console.log(data);
});

// 2. 做其它事, 5s后放入土豆 
console.log('买土豆');
console.log('洗土豆');
console.log('切土豆');

运行结果:


微信截图_20181226174617.png

虽然回调函数能够实现异步,但是回调函数存在以下问题:

1)回调地狱问题:
异步多级依赖的情况下会层层嵌套,代码难以阅读的维护;
2)可能会造成多个异步在某一时刻获取所有异步的结果;
3)异步不支持try/catch回调函数是在下一事件环中取出,
所以一般在回调函数的第一个参数都是用来预置错误对象
4)不能通过return返回结果

2、Promise:

promise,承诺。在代码中我们可以这么理解:此处我先许下个承诺,过了一定时间后我带给你一个结果。

Promise的三种状态

1)Pending
Promise对象实例创建时候的初始状态
2)Fulfilled
成功的状态
3)Rejected
失败的状态

构建Promise
//  promise的方法会立刻执行;
//  两个输出都会打印
let promise = new Promise(() => {     
   console.log('喜欢IT');
});
console.log('就上撩课(itlike.com)');
promise也可以代表未来的一个值

一个promise实例可以多次调用then,当成功后会将结果依次执行

let  promise = new Promise(
   (resolve, reject) => {
    ajax.get(BASEURL + 'api/goods/', 
        (err, data)=>{
        if (err) return reject(err);
        resolve(data);
    })
});
promise.then(data => {    
   console.log(data);
});
promise.then(data => {    
   console.log(data);
});
promise也可以代表一个不用返回的值
 // 代表一个用于不会返回的值
let  promise = new Promise(
     (resolve, reject) => { }
     );
     promise.then(data => {
     console.log(data);
});
Promise.resolve

返回一个Promise实例,这个实例处于resolve状态。

Promise.resolve('成功获取结果')
.then(data=>{ 
    console.log(data);
});
Promise.reject

返回一个Promise实例,这个实例处于reject状态。

Promise.reject('获取结果失败')
.then(data=>{ 
   console.log(data); 
},err=>{ 
   console.log(err); 
})
Promise.race

该方法用于接收一个数组,数组内都是Promise实例,返回一个Promise实例,这个Promise实例的状态转移取决于参数的Promise实例的状态变化。

当参数中任何一个实例处于resolve状态时,返回的Promise实例会变为resolve状态。如果参数中任意一个实例处于reject状态,返回的Promise实例变为reject状态。

Promise.race(
    [readFiles('./a.txt'),
    readFiles('./b.txt')]).then(
data=>{
    console.log({data})
},(err)=>{
    console.log(err)
});
下面通过样例作为演示,我们定义做饭、吃饭、洗碗(cook、eat、wash)这三个方法,它们是层层依赖的关系,下一步的的操作需要使用上一部操作的结果。(这里使用 setTimeout 模拟异步操作)
//做饭
function cook(){
    console.log('开始做饭。');
    var p = new Promise(function(resolve, reject){        //做一些异步操作
        setTimeout(function(){
            console.log('做饭完毕!');
            resolve('鸡蛋炒饭');
        }, 1000);
    });
    return p;
}
 
//吃饭
function eat(data){
    console.log('开始吃饭:' + data);
    var p = new Promise(function(resolve, reject){        //做一些异步操作
        setTimeout(function(){
            console.log('吃饭完毕!');
            resolve('一块碗和一双筷子');
        }, 2000);
    });
    return p;
}
 
function wash(data){
    console.log('开始洗碗:' + data);
    var p = new Promise(function(resolve, reject){        //做一些异步操作
        setTimeout(function(){
            console.log('洗碗完毕!');
            resolve('干净的碗筷');
        }, 2000);
    });
    return p;
}

使用 then 链式调用这三个方法

cook()
.then(function(data){
    return eat(data);
})
.then(function(data){
    return wash(data);
})
.then(function(data){
    console.log(data);
});

当然上面代码还可以简化成如下:

cook()
.then(eat)
.then(wash)
.then(function(data){
    console.log(data);
});
微信截图_20181227161544.png
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容