AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • Início
  • system&network
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • Início
  • system&network
    • Recentes
    • Highest score
    • tags
  • Ubuntu
    • Recentes
    • Highest score
    • tags
  • Unix
    • Recentes
    • tags
  • DBA
    • Recentes
    • tags
  • Computer
    • Recentes
    • tags
  • Coding
    • Recentes
    • tags
Início / coding / Perguntas / 76936887
Accepted
Toby Harnish
Toby Harnish
Asked: 2023-08-20 04:19:42 +0800 CST2023-08-20 04:19:42 +0800 CST 2023-08-20 04:19:42 +0800 CST

O mecanismo JS cria uma nova microtarefa que executará todos os manipuladores encadeados em um objeto Promise quando a resolução for invocada?

  • 772

Recentemente, encontrei esta pergunta no Stack Overflow, perguntando sobre como o método then realmente funciona em JavaScript. O respondente, Trincot, fez o seguinte comentário:

O host verificará quais filas de trabalhos possuem entradas, dando preferência às filas de trabalhos com alta prioridade. Uma fila de tarefas do Promise tem uma prioridade muito alta, normalmente mais alta do que a fila de eventos que lida com a interação do usuário ou outros eventos externos. Portanto, o trabalho que foi colocado na fila na etapa 4 acima é retirado da fila Promise Job. Este trabalho chamará sequencialmente as funções de retorno de chamada que foram registradas como retornos de chamada (como o registrado na etapa 7) no objeto myPromise.

Se entendi sua explicação corretamente, sempre que a função resolve é invocada, o JavaScript agendará uma microtarefa (ou um job) na fila de jobs, que executará todos os callbacks passados ​​para eles, incluindo o encadeamento, quando a pilha de chamadas estiver vazia. Por exemplo:

Promise.resolve("Hi")
    .then(() => {
        console.log("Hi");
    })
    .then(() => {
        console.log("World");
    });

Nesse caso, a promessa é resolvida imediatamente, o que significa que uma microtarefa será agendada imediatamente. Quando os retornos de chamada terminarem a execução, o mecanismo JS verificará se há microtarefas na fila. Como a promessa foi resolvida imediatamente, ele executará a microtarefa, que por sua vez executa todos os manipuladores passados ​​para o método then. Como resultado, o código produzirá "Hi" e "World".

No entanto, por que esse código gera "1 3 2 4" em vez de "1 2 3 4"?

const p1 = Promise.resolve();
const p2 = Promise.resolve();
p1.then(() => {
    console.log(1);
}).then(() => {
    console.log(2);
});
p2.then(() => {
    console.log(3);
}).then(() => {
    console.log(4);
});

Acredito que o código deve gerar "1 2 3 4" em vez de "1 3 2 4". Isso ocorre porque, quando p1 e p2 são resolvidos, duas microtarefas são enfileiradas. À medida que os retornos de chamada terminam a execução, eles adicionam esses retornos de chamada às suas listas internas. Assim que a pilha de chamadas estiver vazia, o mecanismo JS seleciona a tarefa mais antiga da fila e a executa. Essa tarefa deve executar todos os manipuladores passados ​​para essa instância específica do Promise. No entanto, não parece estar acontecendo como o esperado. Alguém poderia me explicar o motivo desse comportamento?

Obrigado pelo seu tempo e tenha um ótimo dia!

javascript
  • 2 2 respostas
  • 48 Views

2 respostas

  • Voted
  1. Best Answer
    trincot
    2023-08-20T04:49:41+08:002023-08-20T04:49:41+08:00

    quando p1 e p2 são resolvidos, duas microtarefas são enfileiradas.

    Isso é um mal-entendido. Uma microtarefa (uma tarefa prometida) é enfileirada quando:

    • um thenmétodo é executado em uma promessa resolvida
    • uma promessa é resolvida e já havia um thenmétodo executado nela antes de ser resolvida: para cada thenretorno de chamada, um trabalho separado é criado.

    Portanto, quando as duas primeiras instruções forem executadas, nada será adicionado à fila de jobs de promessa ainda.

    Perceba que:

    • quando um thenmétodo é executado, seu retorno de chamada é colocado na fila de jobs de promessa somente quando a promessa já foi resolvida. Caso contrário, ele é registrado em espera pela promessa de resolução.
    • Quando um thenmétodo é executado, ele retorna uma promessa que está sempre pendente, mesmo quando é chamado em uma promessa resolvida.

    Pode ajudar a identificar as promessas retornadas por then()chamadas com uma variável e também nomear as funções de retorno de chamada.

    Isso deixaria seu script assim:

    const p1 = Promise.resolve();
    const p2 = Promise.resolve();
    const q1 = p1.then(function p1_then() { console.log(1) });
    const r1 = q1.then(function q1_then() { console.log(2) });
    const q2 = p2.then(function p2_then() { console.log(3) });
    const r2 = q2.then(function q2_then() { console.log(4) });
    

    Aqui está uma visão simplificada sobre o que acontece nesse script:

    • O contexto identifica de onde a ação atual é tomada
    • A ação é a instrução atual que executa
    • Cada promessa nomeada tem sua própria coluna: ?significa que está pendente; Fsignifica que está cumprido.
    • A última coluna lista as entradas atuais na fila de trabalhos de promessa
    Contexto Ação p1 p2 q1 r1 q2 r2 Fila de trabalho de promessa
    Roteiro p1 = Promise.resolve() F - - - - - -
    p2 = Promise.resolve() F F - - - - -
    q1 = p1.then(p1_then) F F ? - - - p1_then
    r1 = q1.then(q1_then) F F ? ? - - p1_then
    q2 = p2.then(p2_then) F F ? ? ? - p1_then,p2_then
    r2 = q2.then(q2_then) F F ? ? ? ? p1_then,p2_then
    Hospedar Conseguir empregop1_then F F ? ? ? ? p2_then
    p1_then console.log(1) F F ? ? ? ? p2_then
    p1_then (retornar) F F F ? ? ? p2_then,q1_then
    Hospedar Conseguir empregop2_then F F F ? ? ? q1_then
    p2_then console.log(3) F F F ? ? ? q1_then
    p2_then (retornar) F F F ? F ? q1_then,q2_then
    Hospedar Conseguir empregoq1_then F F F ? F ? q2_then
    q1_then console.log(2) F F F ? F ? q2_then
    q1_then (retornar) F F F F F ? q2_then
    Hospedar Conseguir empregoq2_then F F F F F ? -
    q2_then console.log(4) F F F F F ? -
    q2_then (retornar) F F F F F F -
    Hospedar nada para fazer F F F F F F -
    • 4
  2. Hard
    2023-08-20T04:49:53+08:002023-08-20T04:49:53+08:00

    Segue a ordem de execução:

    1. O manipulador .then() para p1 registra 1 no console.
    2. O manipulador .then() para p2 registra 3 no console.
    3. O manipulador .then() encadeado para p1 registra 2 no console.
    4. O manipulador .then() encadeado para p2 registra 4 no console.

    então a ordem do processo será 1,3,2,4

    Lembre-se de que, embora o código pareça síncrono, a resolução do Promise e a execução dos manipuladores .then() são processos assíncronos.

    • -2

relate perguntas

  • classificação de mesclagem não está funcionando - código Javascript: não é possível encontrar o erro mesmo após a depuração

  • método select.remove() funciona estranho [fechado]

  • Sempre um 401 res em useOpenWeather () - react-open-weather lib [duplicado]

  • O elemento de entrada não possui atributo somente leitura, mas os campos ainda não podem ser editados [fechado]

  • Como editar o raio do primeiro nó de um RadialTree D3.js?

Sidebar

Stats

  • Perguntas 205573
  • respostas 270741
  • best respostas 135370
  • utilizador 68524
  • Highest score
  • respostas
  • Marko Smith

    destaque o código em HTML usando <font color="#xxx">

    • 2 respostas
  • Marko Smith

    Por que a resolução de sobrecarga prefere std::nullptr_t a uma classe ao passar {}?

    • 1 respostas
  • Marko Smith

    Você pode usar uma lista de inicialização com chaves como argumento de modelo (padrão)?

    • 2 respostas
  • Marko Smith

    Por que as compreensões de lista criam uma função internamente?

    • 1 respostas
  • Marko Smith

    Estou tentando fazer o jogo pacman usando apenas o módulo Turtle Random e Math

    • 1 respostas
  • Marko Smith

    java.lang.NoSuchMethodError: 'void org.openqa.selenium.remote.http.ClientConfig.<init>(java.net.URI, java.time.Duration, java.time.Duratio

    • 3 respostas
  • Marko Smith

    Por que 'char -> int' é promoção, mas 'char -> short' é conversão (mas não promoção)?

    • 4 respostas
  • Marko Smith

    Por que o construtor de uma variável global não é chamado em uma biblioteca?

    • 1 respostas
  • Marko Smith

    Comportamento inconsistente de std::common_reference_with em tuplas. Qual é correto?

    • 1 respostas
  • Marko Smith

    Somente operações bit a bit para std::byte em C++ 17?

    • 1 respostas
  • Martin Hope
    fbrereto Por que a resolução de sobrecarga prefere std::nullptr_t a uma classe ao passar {}? 2023-12-21 00:31:04 +0800 CST
  • Martin Hope
    比尔盖子 Você pode usar uma lista de inicialização com chaves como argumento de modelo (padrão)? 2023-12-17 10:02:06 +0800 CST
  • Martin Hope
    Amir reza Riahi Por que as compreensões de lista criam uma função internamente? 2023-11-16 20:53:19 +0800 CST
  • Martin Hope
    Michael A formato fmt %H:%M:%S sem decimais 2023-11-11 01:13:05 +0800 CST
  • Martin Hope
    God I Hate Python std::views::filter do C++20 não filtrando a visualização corretamente 2023-08-27 18:40:35 +0800 CST
  • Martin Hope
    LiDa Cute Por que 'char -> int' é promoção, mas 'char -> short' é conversão (mas não promoção)? 2023-08-24 20:46:59 +0800 CST
  • Martin Hope
    jabaa Por que o construtor de uma variável global não é chamado em uma biblioteca? 2023-08-18 07:15:20 +0800 CST
  • Martin Hope
    Panagiotis Syskakis Comportamento inconsistente de std::common_reference_with em tuplas. Qual é correto? 2023-08-17 21:24:06 +0800 CST
  • Martin Hope
    Alex Guteniev Por que os compiladores perdem a vetorização aqui? 2023-08-17 18:58:07 +0800 CST
  • Martin Hope
    wimalopaan Somente operações bit a bit para std::byte em C++ 17? 2023-08-17 17:13:58 +0800 CST

Hot tag

python javascript c++ c# java typescript sql reactjs html

Explore

  • Início
  • Perguntas
    • Recentes
    • Highest score
  • tag
  • help

Footer

AskOverflow.Dev

About Us

  • About Us
  • Contact Us

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve