Javascript 无法将回调队列转换为使用承诺

Javascript 无法将回调队列转换为使用承诺,javascript,callback,es6-promise,Javascript,Callback,Es6 Promise,我已经使用Promissions+async/Wait有一段时间了,我认为我对它们很满意,但这种情况确实让我感到困惑。非常感谢您的任何建议/指导 上下文:我的应用程序正在发出URI请求,但我必须将每个请求延迟几秒钟。为了使延迟更准确,我设置了一个队列来发出请求。使用回调没有问题,但我已经做了一段时间了,我似乎不知道如何使用承诺来实现它 沙盒化回调代码如下: const queue = [] let t; function addToQueue(params, cb) { queue.p

我已经使用Promissions+async/Wait有一段时间了,我认为我对它们很满意,但这种情况确实让我感到困惑。非常感谢您的任何建议/指导

上下文:我的应用程序正在发出URI请求,但我必须将每个请求延迟几秒钟。为了使延迟更准确,我设置了一个队列来发出请求。使用回调没有问题,但我已经做了一段时间了,我似乎不知道如何使用承诺来实现它

沙盒化回调代码如下:

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 => ... )


addToQueue
函数中创建一个
newpromise
,并将解析器函数放到队列中。然后,稍后使用获取结果解析承诺:

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()
    }
}

或者,您可以承诺整个队列代码,并使用承诺作为队列本身

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);

addToQueue
函数中创建一个
newpromise
,并将解析器函数放到队列中。然后,稍后使用获取结果解析承诺:

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()
    }
}

或者,您可以承诺整个队列代码,并使用承诺作为队列本身

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);

@PatrickRoberts当
队列
承诺实现时,请求和计时器都会启动,这应该可以正常工作。在响应之后等待2秒也是可能的,它看起来像
queue=result.then(res=>voidres,err=>voiderr.then(计时器)。这太不可思议了,谢谢你,伯吉!看到你把它写出来,我对它有了很大的了解,特别是你是如何传递决心的。我也很感激这个替代方案,我完全忘记了计时器应该在抓取完成后重新启动,我很高兴你发现了这一点!我将再看一会儿,然后尝试一下。@Bergi为什么要使用
queue=result.then(res=>void res,err=>void err.then(timer)
而不是
queue=result.then(timer)
对于在启动计时器之前等待完成的请求?@Sean我使用了
void
来显式地删除该值,以便它可以被垃圾收集-在这里,当您在之后调用
timer
时,也可以执行
queue=result。然后(timer,timer)
:-)更重要的是处理(并忽略)错误,否则
队列
承诺将被拒绝并停止工作。明白了!感谢您的解释。@PatrickRoberts请求和计时器都是在
队列
承诺实现时启动的,应该可以正常工作。在响应之后等待2秒也是可能的,它看起来像
queue=result.then(res=>voidres,err=>voiderr.then(计时器)。这太不可思议了,谢谢你,伯吉!看到你把它写出来,我对它有了很大的了解,特别是你是如何传递决心的。我也很感激这个替代方案,我完全忘记了计时器应该在抓取完成后重新启动,我很高兴你发现了这一点!我将再看一会儿,然后尝试一下。@Bergi为什么要使用
queue=result.then(res=>void res,err=>void err.then(timer)
而不是
queue=result.then(timer)
对于在启动计时器之前等待完成的请求?@Sean我使用了
void
来显式地删除该值,以便它可以被垃圾收集-在这里,当您在之后调用
timer
时,也可以执行
queue=result。然后(timer,timer)
:-)更重要的是处理(并忽略)错误,否则
队列
承诺将被拒绝并停止工作。明白了!谢谢你的解释。