JS中的Promise对象

完成一个异步操作通常分为四步:1.声明注册回调函数的接口。2.声明回调函数。3.注册回调函数。4.调用回调函数。

比如一个网络库,提供了一个registerConnectedCB(const ConnectedCB& cb)的接口(声明了注册接口和回调函数),调用它往网络库中注册了一个连接成功时的回调函数。

这个回调函数的声明形式需要根据实际网络的库的要求和业务的需求进行设计,比如是应该有一个参数还是多个参数,是否应该有一个错误码标识等,这属于编码规范的范畴,这种设计在一些语言中并不被约束,比如在C++中就是如此。

但是在JS中就设计为语言层面的约束了,它通过Promise来统一异步操作的编码流程,规范代码风格。

这篇文章描述了我所认为的Promise几个要点。

Promise对象

Promise对象就像它的命名一样的行为,许诺,代表了一种未来的状态,现在对未来的许诺。MDN上的解释

A <font style="color:rgb(27, 27, 27);">Promise</font> is a proxy for a value not necessarily known when the promise is created.

<font style="color:rgb(27, 27, 27);">Promise</font>代表了当前不需要知道结果的一种操作。启动一个操作,不需要马上知道结果(立即返回),结果会在稍后告知,这是一种异步流程。

**Promise**对象就代表了这类异步流程。

使用Promise对象
  • 通过Promise构造函数创建一个Promise对象

通过Promise构造函数,产生一个promise对象,需要传入一个函数,这个函数就是实际的业务函数,promise对象包装的业务函数,都是异步处理的,所以需要一种方式知道执行的结果。

使用它的then注册结果处理函数,如下代码:

var promise = new Promise(function (resolve){
    console.log("inner promise"); // 1
    resolve(42);
});
promise.then(function(value){
    console.log(value); // 3
});
console.log("outer promise"); // 2
  • 通过Promiseresolve方法返回一个Promise对象

Promise.resolve方法返回一个Promise对象,这个对象会立刻进入resolve状态,其.then中的成功回调会被执行。

Promise.resolve(42).then(function(value){
  console.log(value);
})

等于下面的代码:

let p = new Promise(function(resolve){
  resolve(42);
});

p.then(function(value){
  console.log(value);
});
then方法

Promisethen()方法最多接受两个参数;第一个参数是Promise成功时的回调函数,第二个参数是Promise失败时的回调函数。每个**then()**返回一个新生成的**Promise**对象,这个对象可被用于链式调用。


这个then的返回值分几种情况:

  1. 回调中无返回值,它将返回一个fulfilled状态Promise对象,undefined作为值。
let p = Promise.resolve(1);
p.then(function(res){
    console.log(res); //输出 1
}).then(function(res1){
    console.log(res1); //输出 undefined
})
  1. 回调中有返回值,返回值不是一个Promise对象,则将返回一个为fulfiled状态的promise对象,返回值作为值。
const p1 = Promise.resolve(1);
p1.then((value) => {
    console.log(value); //输出 1
    return value + 1;
}).then((value) => {
    console.log(value); //输出 2
});
  1. 回调函数返回的是一个Promise对象,下一个then中的回调等待这个promise对象执行状态改变后才会执行,要么是fulfilled,要么是rejected。
let p2 = Promise.resolve();
p2.then(()=>{
    //返回一个状态为pending的promise,setTimeout执行后,状态标为fulfilled
    return new Promise((resolve, reject)=>{
        setTimeout(()=>{
          console.log(1);
          resolve();
        },2000);
    });
}).then(()=>{
    console.log(2);//两秒后输出2
});

链式调用

不管注册到then方法中回调返回怎么写,最终都会包装成一个Promise对象,所以再调用这个对象的then就形成了链式调用。

最简单的链式调用就是在回调方法中不返回任何值,后续的回调方法也不需要前面回调的返回值。

function taskA() {
 console.log("Task A");
  return
}

function taskB() {
 console.log("Task B");
}

function onRejected(error) {
 console.log("Catch Error: A or B", error);
}

function finalTask() {
 console.log("Final Task");
}

var promise = Promise.resolve();
promise
 .then(taskA)
 .then(taskB)
 .catch(onRejected)
 .then(finalTask);

taskA–>taskB–>finalTask依次执行,如果在任意函数抛出一个异常,将会走catch方法注册的回调,执行链会终止。

有返回值

function TaskA() {
    return 1;
}

function addTwo(value) {
    return value + 2;
}

function addThree(value) {
    value += 3;
    console.log("final value:"+value);
}

Promise.resolve().then(TaskA).then(addTwo).then(addThree);

上面两种形式都将被包装成fulfilled状态的Promise对象返回。

返回一个Pending的Promise对象,即还需要等上一次异步业务执行的结果确定Promise的状态,如下代码,这个也是一个更具意义的调用链示意代码

function ajax(url,sucessCb,failedCb) {
    //1.创建XMLHttpRequest对象
    var xmlHttp = new XMLHttpRequest();
    //2.发送请求
    xmlHttp.open('GET',url,true);
    xmlHttp.send();
    //3.服务端响应
    xmlHttp.onreadystatechange = function() {
        if (xmlHttp.readyState === 4 && xmlHttp.status === 200) {
            var obj = JSON.parse(xmlHttp.response);
            sucessCb && sucessCb(obj);
        } else if (xmlHttp.readyState === 4 && xmlHttp.status === 404) {
            failedCb && failedCb(xmlHttp.statusText);
        }
    }
}

function getPromise(url) {
    return new Promise((reslove,reject)=> {
        ajax(url,reslove,reject);
    })
}

getPromise('static/a.json').then(res=>{
    console.log(res);
    return getPromise('static/b.json');
}).then(res=>{
    console.log(res);
    return getPromise('static/c.json');
},err=>{
    console.log(err);
    return getPromise('static/d.json');
}).then(res=>{
    console.log(res);
})

顺序请求网络内容,a.json->b.json->c.json->d.json,每个then中的回调都返回一个pending的Promise对象。

参考资料:

  1. https://juejin.cn/post/7052942288581820446
  2. https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Promise/then
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

mo4776

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值