一点对Promise的理解与总结

全手打原创,转载请标明出处:http://www.javashuo.com/article/p-cjmwmnvf-hn.html,多谢,=。=~ html

 

axios用多了就开始疑惑它里面究竟是个啥,虽然总被告知它就是基于ajax的封装,但掐指一算,事情应该没这么简单,因而开始深挖,挖着挖着就挖到了Promise。毕竟axios的官方描述是这样的:Promise based HTTP client for browser and node.js。而axios其中一个特色就是Supports the Promise API,之前只知道promise是一种替代层层回调的解决方案,但如今看来我认为颇有必要详细的研究一下。node

 

背景ios

在JavaScript的世界中,全部代码都是单线程执行的。该特性致使JavaScript的全部网络操做,浏览器事件,都必须是异步执行(不然容易发生阻塞)。异步执行能够用回调函数实现,该方式会在未来的某个时间点触发一个函数调用(回调)。但异步执行中的回调并不利于代码复用,例如:ajax

request.onreadystatechange = function () {
    if (request.readyState === 4) {
        if (request.status === 200) {
            return success(request.responseText);
        } else {
            return fail(request.status);
        }
    }
}

但若是是这样的链式写法就会好不少(先统一执行AJAX逻辑,不关心如何处理结果,而后,根据结果是成功仍是失败,在未来的某个时候调用success函数或fail函数):axios

var ajax = ajaxGet('http://...');
ajax.ifSuccess(success)
    .ifFail(fail);

 

什么是Promise?promise

上述“承诺未来会执行”的对象在JavaScript中称为Promise对象,它有各类开源实现,但后面ES6将其写进了语言标准,统一了用法,原生提供了Promise对象,由浏览器直接支持。浏览器

Promise对象表明一个异步操做,有三种状态:Pending(进行中)、Resolved(已完成,又称Fulfilled)和Rejected(已失败)。网络

Promise是一个容器,里面保存着某个将来才会结束的事件(一般是一个异步操做)的结果。dom

ES6规定,Promise对象是一个构造函数,用来生成Promise实例:ecmascript

var promise = new Promise(function(resolve, reject) {
  // ... some code

  if (/* 异步操做成功 */){
    resolve(value);
  } else {
    reject(error);
  }
});

resolve:在异步操做成功时调用,并将异步操做的结果,做为参数传递出去;

reject:在异步操做失败时调用,并将异步操做报出的错误,做为参数传递出去;

 

Promise实例生成之后,能够用then方法、catch方法分别指定Resolved状态和Rejected状态的回调函数:

// Promise测试(then、catch)
new Promise(function(resolve,reject) {
    let num = Math.random() * 2;
    console.log("产生的随机数为:" + num);
    setTimeout(function () {
        if(num < 1) {
            console.log("即将执行成功");
            resolve("200 OK");
        } else {
            console.log("即将执行失败");
            reject("失败的缘由是num为:" + num);
        }
    }, num * 1000);
}).then(function(r) {
    console.log("then:" + r);
}).catch(function(j) {
    console.log("catch:" + j);
});

 

PS:只用then也能够代替上述效果,由于then能够接受两个回调函数做为参数,第二个参数可选。第一个回调函数是Promise对象的状态变为Resolved时调用,第二个回调函数是Promise对象的状态变为Rejected时调用:

promise.then(function(value) {
  // success
}, function(error) {
  // failure
});

 

链式多任务串行

有若干个异步任务,须要先作任务1,若是成功后再作任务2,任何任务失败则再也不继续并执行错误处理函数。要串行执行这样的异步任务,不用Promise须要写一层一层的嵌套代码,而使用Promise则能够采用链式写法:job1.then(job2).then(job3).catch(handleError)

// Promise测试(多任务串行执行)
var p = new Promise(function (resolve, reject) {
    console.log("resolve开始");
    resolve(8);
});

function multi(param) {
    return new Promise(function(resolve, reject) {
        console.log("计算" + param + "*" + param + ":");
        setTimeout(resolve, 1500, param * param);
    });
};

function add(param) {
    return new Promise(function(resolve, reject) {
        console.log("计算" + param + "+" + param + ":");
        setTimeout(resolve, 1500, param + param);
    });
};

p.then(multi).then(add).then(multi).then(function(param){
    console.log("获得最终的值为:" + param);
});

 

Promise.all()实现多任务并行

一个页面聊天系统,咱们须要从两个不一样的URL分别得到用户的我的信息和好友列表,这两个任务是须要并行执行的,用Promise.all()实现以下:

var p1 = new Promise(function (resolve, reject) {
    setTimeout(resolve, 500, 'P1');
});
var p2 = new Promise(function (resolve, reject) {
    setTimeout(resolve, 600, 'P2');
});
// 同时执行p1和p2,并在它们都完成后执行then:
Promise.all([p1, p2]).then(function (results) {
    console.log(results); // 得到一个Array: ['P1', 'P2']
});

 

Promise.race()实现多任务赛跑

有些时候,多个异步任务是为了容错。好比,同时向两个URL读取用户的我的信息,只须要得到先返回的结果便可,其余任务的结果会被丢弃。这种状况下,用Promise.race()实现:

var p1 = new Promise(function (resolve, reject) {
    setTimeout(resolve, 500, 'P1');
});
var p2 = new Promise(function (resolve, reject) {
    setTimeout(resolve, 600, 'P2');
});
Promise.race([p1, p2]).then(function (result) {
    console.log(result); // 'P1'
});

 

参考资料

Promise:https://www.liaoxuefeng.com/wiki/1022910821149312/1023024413276544

ECMAScript 6 Promise对象:https://www.w3cschool.cn/ecmascript/3uge1q5v.html

相关文章
相关标签/搜索