Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to yield value multiple times from function?

So what I am doing is, I have 2 files, One that contain a script which would generate a token and the second file handle that token.

The problem is that the second script which would log the token it would only log the first token received.

This is the how I am handling the token:

const first_file = require("./first_file.js");
first_file.first_file().then((res) => {
    console.log(res);
});

And clearly that wouldn't work, Because it's not getting updated with the newer value.

first_file = async () => {
    return new Promise(async (resolve, reject) => {
        //Generating the token
        (async () => {
            while (true) {
                console.log("Resolving...");
                resolve(token);
                await sleep(5000);
                resolved_token = token;
            }
        })();
    });
};

module.exports = { first_file };

What I am doing here is, I tried to do a while..loop so that I keep resolving the token. But it didn't, Is there and way I can export the variable directly so the task would be easier ?

like image 536
DUMBUSER Avatar asked Mar 01 '23 15:03

DUMBUSER


1 Answers

If I understand your question correctly, You want to resolve promise multiple times, And It's nothing to do with modules...

But You understand something wrong about promise in JavaScript...
You can't resolve a promise twice.

Generator

But you can generate new value from function, this type of function also known as generator, Where a function can reenter its context (Something like async/await) and yield result using yield keyword.

Usually a generator is used in for..of loop. It has next() method for yield next value from a generator...

Lets look an example:

const delay = ms => new Promise(res => setTimeout(res.bind(null, ms), ms));

async function* generator() {
    yield 'yield result from generator!'
    for (let ms = 100; ms <= 300; ms += 100) {
        yield 'delay: ' + await delay(ms) + ' ms';
    }
    yield delay(1000).then(() => 'you can also yield promise!');
}

async function main() {
    const gen = generator();
    console.log('1st', (await gen.next()).value);
    for await (const ms of gen) {
        console.log(ms)
    }
}

main()

Note that * after function, So that we know that this function a generator, with async keyword this is Async Generator.

Generator is very useful. like: Generate value on demand, Pass data like pipe!, Can return endless value from function etc...

Callback

This old school method heavily used in node, Where you pass a callback function as argument.

Example:

const delay = ms => new Promise(res => setTimeout(res.bind(null, ms), ms));

async function callback(fn) {
    fn('yield result from callback!');
    for (let ms = 100; ms <= 300; ms += 100) {
        fn('delay: ' + await delay(ms) + ' ms');
    }
    await delay(1000);
    fn('yield asynchronously!');
}

callback(value => console.log(value));

This approach create all sort of nutsy problem, like: created function scope, disaster of control flow, doesn't have break keyword etc... I don't recommend this method.

like image 110
Nur Avatar answered Mar 11 '23 22:03

Nur