Javascript Promise 多次返回.
Posted bywayboy
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Javascript Promise 多次返回.相关的知识,希望对你有一定的参考价值。
在JS中 我们使用Promise 可以带来极大地方便。然而,一个Promise 只要 resolve 或者 reject一次后,后续的resolve 或者 reject调用都会被忽略。因为此时 Promise对象已经结束了 Pending 状态。
然而,更多的时候,为了得到更好的用户使用体验,我们向服务器发送一个请求,并不急于等待服务器返回结果,而是在服务器真正完成这次请求之前,向用户展示更多的工作状态信息。 这在 http 请求中很少出现这种请求。但当使用WebSocket的时候。我们就迫切需要实现这种功能。
例如如下业务场景:
我们在浏览器中使用条码枪扫描用户的付款码。 同时发起一笔交易。这个时候。服务器可能要做如下工作:
- 表单校验、检查产品库存。
- 向微信、支付宝发起交易请求。
- 创建订单
- 订单创建失败 则要发起退款,否则完成交易。
在实际场景中,步骤1一般是很快就能完成的,步骤 2 需要等待一些时间 步骤3和4也很快。
步骤一期是不是必须,只不过是为了减少向微信发起不必要的交易请求而已。步骤3 则有失败的可能。因为创建订单的时候我们肯定是要检查锁定库存的,这个时候如果库存不足、或者过了可以交易时间则很可能交易失败。退款也会有一个过程。
在使用http协议请求的情况下,我们从提交数据到等待结果 刚好是一个resolve 或者 reject 在这过程中,我们只知道服务器在干活,并不知道具体细节。如果使用WebSocket 我们假定发起一笔交易后服务器有如下信息返回:
{"success": true, "done":false, "message": “正在发起微信收款...”}
{"success": true, "done":false, "message": "用户正在付款..."}
{"success": true, "done":false, "message":"付款完成, 正在创建订单..."}
{"success": true, "done":true, "message": "交易成功!"}
服务器总共返回了4条信息, success 代表是否是出错的信息, done 代表是否是最后一条消息。这个时候一个Promise 肯定无法满足要求。这个时候我们要对 Promise 做一个小小的扩展。收到 done=false的消息的时候,调用 update 更新信息,当收到最后一条消息的时候调用 resolve 或者reject 。实现代码如下:
/**
*
* @param {((resolve: (value: any) => void, reject: (reason?: any) => void,, update: (reason?: any) => void) => void} fn
* @returns {PromiseEx}
*/
function PromiseEx(fn){
let _fn = [], _resolve, _reject, p;
this.then = fn=>{
p.then(fn);
return this;
}
this.catch = fn=>{
p.catch(fn);
return this;
}
this.update = fn=>{_fn.push(fn); return this;}
const update = (o)=>{
_fn.forEach(_cb=>_cb(o));
}
p = new Promise((resolve, reject)=>{
fn(resolve, reject, update);
})
return this;
}
new PromiseEx((resolve, reject, update)=>{
let i = 0;
let id = setInterval(() => {
update(i++);
if(i == 5){
clearInterval(id);
resolve({done:true})
}
}, 1000);
}).then(res=>{
console.log('then', res)
}).update(res=>{
console.log('update', res)
});
以上是关于Javascript Promise 多次返回.的主要内容,如果未能解决你的问题,请参考以下文章
Javascript Promise:在 Promise 解决之前返回“正在进行”响应?