Как создать собственную асинхронную работу в теле обещания? - PullRequest
0 голосов
/ 04 января 2019

Я пишу функцию, которая эмулировала большую работу. Мне нужно получить вывод:

Work started.
Hello!
Work done.
Bob

Это мой пример "Hello World":

function bigWork(user){
    console.log('Work started.');
    const p = new Promise(resolve => {

        setTimeout(() => {
            // here is some long calculatin must
            // be done async. Therefore I placed
            // it inside of setTimeout() function
            for(let n = 0; n < 100000; n++);

            console.log('Work done.');
            resolve(user);
        },0);
    });
    return p;
}

bigWork({name:'Bob', age:30}).then(user=> console.log(user.name));
console.log('Hello!');

Его вывод такой же, как я ожидал. Но я вынужден использовать для этого функцию setTimeout(). Я намеренно использую функцию setTimeout() для получения нужного мне вывода на консоль.

Могу ли я получить тот же вывод без использования функции setTimeout()?

Ответы [ 3 ]

0 голосов
/ 04 января 2019

Насколько я понимаю, вы хотите что-то вроде ниже.

  async function bigWork(user){
    console.log('Work started.');
    const p = await longCalculation(100, user);
  	console.log('Work done.');
    return p;
}

function longCalculation(round, user){
     return new Promise((resolve) => {
     	for(let n = 0; n < round; n++);
       resolve (user);
     })
}

bigWork({name:'Bob', age:30}).then(user=> console.log(user.name));
console.log('Hello!');
0 голосов
/ 04 января 2019

Вы можете использовать Promise.resolve:

function bigWork(user){
    console.log('Work started.');
    return Promise.resolve().then(() => {
        for(let n = 0; n < 100000; n++);
        console.log('Work done.');
        return user;
    });
}

bigWork({name:'Bob', age:30}).then(user=> console.log(user.name));
console.log('Hello!');

Имейте в виду, что, хотя это обеспечивает требуемый порядок, оно не препятствует блокированию выполнения во время выполнения цикла for: это происходит в определенном порядке, где "работа" "откладывается до тех пор, пока текущий стек выполнения не станет пустым.

0 голосов
/ 04 января 2019

Извините, что сломал его, но технически JavaScript является однопоточным.

Причина, по которой это работает для вас, заключается в том, что код setTimeout появляется только после завершения основного "потока", поэтому, пока ваш цикл блокирует javascript, ваше приложение-пример не показывает, что это происходит.

Что вы можете сделать, так это использовать WebWorkers, которые обеспечат желаемую многопоточность, но сами по себе являются целым зверем https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API

...