无法将回调队列转换为使用Promise

时间:2019-01-30 17:02:42

标签: javascript callback es6-promise

我已经使用了promise + async / await一段时间了,我以为我对它们感到满意,但是这种情况确实让我感到困惑。任何建议/指导都将不胜感激!

上下文:我的应用程序正在发出URI请求,但是我必须将每个请求延迟几秒钟。为了使延迟更准确,我设置了一个队列来提出请求。使用回调没问题,但是我已经使用了一段时间了,而且我似乎无法全神贯注于如何使用promises实现它。

将以下回调代码沙盒化:

const queue = []
let t;

function addToQueue(params, cb) {
    queue.push({params,cb})
    _run()
}
function _run() {
    if (!t && queue.length) {
        const {params,cb} = queue.shift()
        _dummyFetch(params).then( data => cb(data) )
        _startTimer()
    }
}
function _startTimer() {
    t = setTimeout( _endTimer, 2000 )
}
function _endTimer() {
    t = null
    _run()
}
async function _dummyFetch() {}

沙盒调试:

function seconds() { return Math.round(new Date().getTime()/1000) }
function log(t) { console.log(t + " " + seconds()) }
function logFn(t) { return () => log(t) }

log("init")
addToQueue({}, logFn("request 1")) // should be close/same as init time
addToQueue({}, logFn("request 2"))
addToQueue({}, logFn("request 3"))


// If I could figure out how to make it a promise:
// addToQueue( ... ).then( data => ... )

1 个答案:

答案 0 :(得分:2)

new Promise函数中创建一个addToQueue并将解析器函数放在队列中。然后,稍后通过获取结果来解决promise:

function addToQueue(params) {
    return new Promise(resolve => {
        queue.push({params, resolve})
        _run()
    })
}
function _run() {
    if (!t && queue.length) {
        const {params, resolve} = queue.shift()
        resolve(_dummyFetch(params))
        _startTimer()
    }
}

或者,您可以使整个队列代码分散,并将promise用作队列本身。

const queue = Promise.resolve();

function addToQueue(params) {
    const result = queue.then(() => _dummyFetch(params));
    queue = queue.then(timer);
    return result;
}
function timer() {
    return new Promise(resolve => {
        setTimeout(resolve, 2000);
    });
}
async function _dummyFetch() {}

如果花费的时间超过2秒,您甚至可以让队列等待提取,这样,只需更改即可使两个请求永远不会同时运行

queue = Promise.all([result, queue.then(timer)]).then(res => void res, err => void err);