为什么我的承诺不定? [英] Why is my promise returning undefined?

查看:90
本文介绍了为什么我的承诺不定?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

背景



我试图做一个功能,将异步功能的执行延迟X ms。



出于本演示的目的,以下是异步功能,它接收一个URL:

  / * 
*这是异步功能的模拟。有想象力!
* /
let asyncMock = function(url){
return new Promise(fulfill => {

setTimeout(()=> {
满足({
url,
数据:香蕉
});
},10000);

});
};



目标



我的目标是有一个函数,它将采用 url 参数 asyncMock ,然后每X ms调用一次,直到没有



基本上,我希望每个调用 asyncMock 被X ms分隔。 >

作为一个例子,我想象我连续20次呼叫$ code> asyncMock 。通常这20个电话会立即进行。我想要的是,确保20个电话中的每一个之间有Xms的延迟。



暂定



我的想法是解决这个问题,是有一个工厂,这将返回一个 promise 将在X ms后执行该功能。

 让throttleFactory = function(args){

let {
$节省
} = args;

let promise = Promise.resolve();

let throttleAsync = function(url){

return promise.then(()=> {

setTimeout(anUrl =>
返回新的承诺(履行=> {
履行(asyncMock(anUrl));
});
},throttleMs,url);
});
};

return Object.freeze({
throttleAsync
});
};

理想情况下,我将使用这个工厂,如下例所示:

  let throttleFuns = throttleFactory({
throttleMs:2000
});

console.log('running');

throttleFuns.throttleAsync('http://www.bananas.pt')
.then(console.log)
.catch(console.error);

throttleFuns.throttleAsync('http://www.fruits.es')
.then(console.log)
.catch(console.error);

throttleFuns.throttleAsync('http://www.veggies.com')
.then(console.log)
.catch(console.error);
//代码中的随机位置中的一吨其他电话



问题



这里的问题是我的 throttleAsync fucntion立即输出 undefined 三次。我相信这可能是因为我没有正确地定义 promise



问题



如何解决这个代码按照预期工作?

解决方案

因为 throttleAsync 返回调用 promise.then 的结果,而然后回调不返回任何东西这使得然后创建的承诺的值为 undefined



您可能希望让您恢复您正在创建的新承诺,但是直到 setTimeout 回调才会执行此操作。你想先做(但还有更多,继续阅读):

 让throttleAsync = function(url){

返回promise.then(()=> {
返回新的Promise(履行=> {
setTimeout(anUrl => {
履行(asyncMock(anUrl) );
},throttleMs,url);
});
});
};

还没有理由通过 setTimeout 像这样,所以:

 让throttleAsync = function(url){

return promise。那么(()=> {
返回新的Promise(履行=> {
setTimeout(()=> {
履行(asyncMock(url));
} ,throttleMs);
});
});
};

最初我虽然承诺没有必要,但是您已经澄清,您希望确保重复的呼叫由 throttleMs 间隔开。为了做到这一点,我们将使用上述内容,但是更新 promise

  let throttleAsync = function(url){

return promise = promise.then(()=> {
// ^^^^^^^^
返回新的承诺(履行=> {
setTimeout(()=> {
履行(asyncMock(url));
},throttleMs);
});
});
};

这样,下一次调用 asyncThrottle



直播示例:



  const throttleMs = 1000; const asyncMock = url => url; let promise = Promise.resolve(); let throttleAsync = function(url){return promise = promise.then(()=> {// ^^^^^^^^^返回新的Promise(fulfill => ; {setTimeout(()=> {fulfill(asyncMock(url));},throttleMs);});});}; console.log('running'); throttleAsync('http://www.bananas .pt()。((console.log)).catch(console.error); throttleAsync('http://www.fruits.es').then(console.log).catch(console.error); throttleAsync 'http://www.veggies.com').then(console.log).catch(console.error);  

/ p>

Background

I am trying to make a function that delays the execution of asynchronous functions by X ms.

For the purposes of this demonstration, the following is the async function, which takes an URL:

/*
 *  This is a simulation of an async function. Be imaginative! 
 */
let asyncMock = function(url) {
    return new Promise(fulfil => {

        setTimeout(() => {
            fulfil({
                url,
                data: "banana"
            });
        }, 10000);

    });
};

Objective

My objective here is to have a function, that will take the url argument of asyncMock and then call it every X ms or until there are no more arguments left.

Basically, I want every invocation of asyncMock to be separated by X ms.

As an example, imagine I call asyncMock 20 times in a row. Normally, those 20 calls would be done immediately. What I want, it to make sure that there is Xms of delay between each of the 20 calls.

Tentative

My idea to solve this, is to have a factory, that will return a promise that will execute the function after X ms.

let throttleFactory = function(args) {

    let {
        throttleMs
    } = args;

    let promise = Promise.resolve();

    let throttleAsync = function(url) {

        return promise.then(() => {

            setTimeout(anUrl => {
                return new Promise( fulfil => {
                    fulfil(asyncMock(anUrl));
                });
            }, throttleMs, url);
        });
    };

    return Object.freeze({
        throttleAsync
    });
};

Ideally I would use this factory like in the example bellow:

let throttleFuns = throttleFactory({
    throttleMs: 2000
});

console.log('running');

throttleFuns.throttleAsync('http://www.bananas.pt')
    .then(console.log)
    .catch(console.error);

throttleFuns.throttleAsync('http://www.fruits.es')
    .then(console.log)
    .catch(console.error);

throttleFuns.throttleAsync('http://www.veggies.com')
    .then(console.log)
    .catch(console.error);
// a ton of other calls in random places in code

Problem

The problem here is that my throttleAsync fucntion outputs undefined three times immediately. I believe this might be because I am not defining promise properly.

Question

How can I fix this code to work as intended?

解决方案

Because throttleAsync returns the result of calling promise.then, and the then callback doesn't return anything. This makes the promise created by then resolve with the value undefined.

You probably meant to have it return the new promise you're creating, but you're not doing that until the setTimeout callback. You want to do it prior (but there's more, keep reading):

let throttleAsync = function(url) {

    return promise.then(() => {
        return new Promise( fulfil => {
            setTimeout(anUrl => {
                fulfil(asyncMock(anUrl));
            }, throttleMs, url);
        });
    });
};

There's also no reason to pass the URL through setTimeout like that, so:

let throttleAsync = function(url) {

    return promise.then(() => {
        return new Promise( fulfil => {
            setTimeout(() => {
                fulfil(asyncMock(url));
            }, throttleMs);
        });
    });
};

Originally I though the promise there was unnecessary, but you've clarified that you want to ensure that repeated calls are "spaced out" by throttleMs. To do that, we'd use the above, but update promise:

let throttleAsync = function(url) {

    return promise = promise.then(() => {
    //     ^^^^^^^^^
        return new Promise( fulfil => {
            setTimeout(() => {
                fulfil(asyncMock(url));
            }, throttleMs);
        });
    });
};

This way, the next call to asyncThrottle will wait until the previous one has fired before starting the next.

Live Example:

const throttleMs = 1000;

const asyncMock = url => url;

let promise = Promise.resolve();

let throttleAsync = function(url) {

    return promise = promise.then(() => {
    //     ^^^^^^^^^
        return new Promise( fulfil => {
            setTimeout(() => {
                fulfil(asyncMock(url));
            }, throttleMs);
        });
    });
};

console.log('running');

throttleAsync('http://www.bananas.pt')
    .then(console.log)
    .catch(console.error);

throttleAsync('http://www.fruits.es')
    .then(console.log)
    .catch(console.error);

throttleAsync('http://www.veggies.com')
    .then(console.log)
    .catch(console.error);

这篇关于为什么我的承诺不定?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆