Promise 怎样封装?
新人入门,请多多指教。 生成一个随机数,如果大于0.9则返回成功,否则返回失败,并重新生成随机数,直到返回成功为止。 怎样用Promise 来写? (相当于请求一个网址,成功返回请求成功,失败则继续请求,直到成功为止)如果失败后等待一秒再请求呢,该咋样写?
6 回复
你的问题好像和Promise关系不大,简单的回调就搞定了。Promise是为异步编程提供一种同步抽象,就是可以有返回值和catch异常。一般在一个想对复杂的异步流程里面会非常有用,对于这种,我一般会用组合的方式,就是前一个promise的返回作为下一个的输入,然后在最后面catch异常。如果你能将promise和generator结和一下,那写出的代码想对就比较优雅了。
之前的代码delay有问题,特地重构了下。假设有一个HTTP请求
function fetchComList() {
return new Promise(function (resolve, reject) {
var xhr = new XMLHttpRequest();
xhr.open('GET', '/companies', true);
xhr.onreadystatechange = function () {
if (xhr.readyState === 4) {
xhr.status === 200 ? resolve(xhr.responseText) : reject(xhr.responseText);
}
};
xhr.send();
});
}
Promise Retry
function promiseRetry(opts) {
var originalFn;
//设置
opts = Object.assign({
times: 0,
delay: 0
}, opts);
return function exec(fn) {
if (!originalFn) originalFn = fn;
return fn().catch(function (error) {
if (opts.times-- <= 0)return Promise.reject(error);
return exec(delay);
});
};
//延时处理
function delay() {
return new Promise(function (resolve) {
setTimeout(function () {
resolve(originalFn());
}, opts.delay);
})
}
}
var promiseRetryInstance = promiseRetry({times: 2, delay: 2000});
promiseRetryInstance(fetchComList).then(function (data) {
console.log(data)
}).catch(function (err) {
console.log(err);
});
Rxjs Retry
@htoooth 提到的Rxjs版本
function rxRetry(fn, opts) {
opts = Object.assign({
times: 0,
delay: 0
}, opts);
return Rx.Observable
.defer(function () {
return fn();
})
.retryWhen(function (errs) {
return errs
.zip(Rx.Observable.range(1, opts.times), function (x, y) {
return y
})
.flatMap(function () {
return Rx.Observable.timer(opts.delay);
});
})
}
rxRetry(fetchComList, {times: 2, delay: 2000}).subscribe(function (data) {
console.log(data);
}, function (err) {
console.log(err)
});
import Rx from "rx";
let count = 0;
const random = (cb) => {
console.log("one" + (count++));
let result = Math.random();
if (result > 0.9) {
cb(null, result);
} else {
cb("error");
}
};
const source = Rx.Observable.defer(() => Rx.Observable.fromNodeCallback(random)())
.retryWhen(err => err
.zip(Rx.Observable.range(1, 3), (x, y) => y)
.flatMap(x => Rx.Observable.timer(1000))
);
const subscription = source.subscribe(
function(x) {
console.log('Next: ' + x);
},
function(err) {
console.log('Error: ' + count);
},
function() {
console.log('Completed' + count);
});
这种情况就很种使用,rxjs,而不是 promise。
var Promise = require('bluebird');
function request() {
return new Promise(function (resovle, reject) {
setTimeout(function() {
var num = Math.random();
if(num > 0.8){
resovle(num);
}else{
reject(num);
}
},1000);
})
}
function digui() {
return request().then(function(res) {
console.log('成功 ' + res);
return;
}).catch(function(err) {
console.log('失败 ' + err);
return digui();
})
}
digui().done();