v2.0

Loop

Como criar iterações e percorrer listas no browserMate usando Iterações de Listas, variáveis de controle e condições de rota.

Como o loop funciona

O browserMate não tem um card de "loop" com ícone próprio no canvas. A técnica de loop é implícita e inteligente, sendo sempre o fluxo voltando para uma etapa anterior através de uma condição de rota. Existem duas formas de montar isso:

A condição de rota não precisa estar numa etapa de Decisão Como explicado em Decisão, o campo Definir a próxima Etapa após execução existe em qualquer tipo de etapa, Regra Customizada incluída. Nos exemplos desta página, o passo "Verificar" aparece como uma etapa de Decisão separada porque isso deixa o fluxo mais legível, não porque é a única forma de fazer o desvio. Nada impede de declarar a mesma condição diretamente na etapa de Regra Customizada anterior, unificando Avançar e Verificar numa única etapa. É exatamente o que Iterações de Listas faz.

O padrão de 4 etapas

Pensando de forma independente do mecanismo, todo loop segue a mesma forma:

  1. Inicializar: Prepara a lista ou variáveis de controle antes da primeira iteração.
  2. Verificar: Decide se ainda há o que processar. Se não, sai do loop; se sim, segue.
  3. Processar: Etapa(s) de Execução que operam sobre o item atual.
  4. Avançar: Consome o item processado e volta para o passo de Verificar.

Com Iterações de Listas, os passos 2 (Verificar) e 4 (Avançar) colapsam numa única etapa: a mesma etapa de Regra Customizada consome o item da lista e decide se volta, através da sua própria condição de rota. No controle manual, os quatro passos continuam separados, e o passo 2 nem precisa ser uma etapa de Decisão dedicada, embora normalmente seja mais claro assim. A seção seguinte mostra a forma nativa; Loop sobre uma lista mais abaixo mostra a construção manual completa.

Iterações de Listas: consumindo a lista automaticamente

Toda etapa de 🔢 Regra Customizada tem uma seção Iterações de Listas, logo abaixo de Variáveis do Fluxo no painel, independente de ter ou não código customizado preenchido. A lista a percorrer pode vir de uma Coleção, de uma resposta de API, de uma variável global do tipo Lista, de uma variável local do tipo Lista, criada em Variáveis do Fluxo, ou de uma variável gravada por script (bm.done, globalData.set), desta etapa ou de outra: o seletor mostra as listas com o selo [ ] e as de script sem ele, porque o tipo delas vem da execução. A iteração roda depois das variáveis e dos scripts da mesma etapa, e o Timer de Espera da etapa, se houver, roda por último, depois da iteração. No exemplo a seguir, "Insere Registros no ERP" processa uma empresa por vez a partir da variável lista EMPRESA_LIST, e a etapa seguinte, "Confere Lista Processada", decide se volta para processar a próxima empresa ou segue em frente. "Insere Registros no ERP" referencia EMPRESA_LIST normalmente no seu mapeamento, pegando o item que está na posição atual da lista:

Mapeamento da etapa Insere Registros no ERP referenciando a lista
Mapeamento da etapa "Insere Registros no ERP": o campo referencia a variável lista para pegar o item da vez.

Repare na expressão do mapeamento: {EMPRESA_LIST}[]. Colchetes vazios logo após a variável lista sempre pegam o primeiro registro do array, o mesmo item que "Confere Lista Processada" vai descartar da lista ao avançar (direção Próximo, o padrão, explicada abaixo).

É em "Confere Lista Processada" que as duas peças se encontram: a mesma etapa que avança a lista também declara a condição de rota que decide se o processo volta para "Insere Registros no ERP" ou segue adiante. iteração e roteamento juntos, numa única etapa:

Painel Condições de Rotas e Execuções configurado na etapa Confere Lista Processada
"Confere Lista Processada": a Condição de Rotas (SE EMPRESA_LIST.length > 0, IR Insere Registros no ERP) que decide se o loop volta ou segue.

O que a seção Iterações de Listas faz, tecnicamente, é o conceito de iteração: varrer a lista automaticamente, item por item, sem precisar escrever esse controle manualmente. A direção escolhida para cada variável define o sentido da varredura:

Uma mesma etapa aceita mais de uma variável lista ao mesmo tempo, cada uma com sua própria direção, útil quando várias listas andam em paralelo, item a item (por exemplo, as colunas de uma Coleção: empresa, CNPJ, serviço e UF avançando juntos a cada iteração):

Painel Iterações de Listas com as variáveis EMPRESA_LIST, CNPJ_LIST, SERVICO_LIST e UF_LIST configuradas na mesma etapa
EMPRESA_LIST, CNPJ_LIST, SERVICO_LIST e UF_LIST na mesma etapa. Cada uma com sua direção, todas avançando juntas a cada execução.

Isso substitui a necessidade de escrever bm.get() / bm.done() só para avançar um índice: a própria plataforma encurta a lista uma posição a cada vez que a etapa roda. O que sobra para você configurar é a condição de rota da mesma etapa, decidindo se ainda há itens (loop continua) ou não (segue em frente):

Condição de rota da etapa "Confere Lista Processada"
Regra 1:
  Condição: {EMPRESA_LIST}.length > 0
  Ir para:  Insere Registros no ERP   // volta para reprocessar o próximo item

// sem regra que bata (lista vazia) → segue para a próxima etapa da sequência

A variável lista entra na condição como lista: .length, [0] e .includes() funcionam direto sobre ela, e {EMPRESA_LIST} > 0 tem o mesmo efeito de {EMPRESA_LIST}.length > 0. Detalhes das operações com lista: Lógica de Rotas → Arrays e listas.

Quando usar Iterações de Listas em vez do controle manual Use Iterações de Listas sempre que já existir uma variável lista pronta para percorrer, por exemplo, vinda de uma Coleção de um Obter Informação. Para casos sem uma lista pronta (aguardar uma condição mudar, paginação com total desconhecido), o controle manual das próximas seções continua sendo o caminho.

Loop sobre uma lista (construção manual)

Quando não usar Iterações de Listas, por exemplo se quiser lógica própria a cada avanço, o mesmo resultado é construído manualmente, passo a passo:

Os exemplos abaixo usam Node.js, mas o mesmo padrão vale para Python. bm.get(), bm.done() e bm.bmLog() existem igualmente nas duas linguagens (veja Código Inline → API de contexto do processo). A Etapa 1 abaixo tem sua versão em Python logo em seguida, como referência de tradução. bm.get() devolve a lista como lista (array no Node.js, list no Python), e o número gravado pelo bm.done() como número.

Etapa 1. "Inicializar Loop" (Regra Customizada · Node.js)
const lista = bm.get('{lista_nfs}', []);
const total = lista.length;

bm.done('init', {
  '{loop_index}': 0,
  '{loop_total}': total,
  '{item_atual}': lista[0] || '',
  '{tem_mais}':   total > 0 ? 'sim' : 'nao'
});
Etapa 1. "Inicializar Loop" (Regra Customizada · Python)
lista = bm.get('{lista_nfs}', [])
total = len(lista)

bm.done('init', {
    '{loop_index}': 0,
    '{loop_total}': total,
    '{item_atual}': lista[0] if total > 0 else '',
    '{tem_mais}':   'sim' if total > 0 else 'nao'
})
Etapa 2: "Verificar Loop" (Decisão 🔷, ou a mesma condição direto na etapa anterior ou seguinte, veja a nota acima)
Rota 1:
  Condição: {tem_mais} == 'nao'
  Ir para:  Finalizar Processo

Rota 2:
  Condição: true
  Ir para:  Processar Item
Etapa 3. "Processar Item" (Execução ⚙️)
// Use {item_atual} em qualquer campo de texto desta etapa
Navegar para: https://sistema.com/nf/{item_atual}
(... outras ações sobre o item ...)
Etapa 4. "Avançar Loop" (Regra Customizada · Node.js) → Ir para "Verificar Loop"
const lista = bm.get('{lista_nfs}', []);
const idx   = bm.get('{loop_index}') + 1;

bm.done('avancou', {
  '{loop_index}': idx,
  '{item_atual}': lista[idx] || '',
  '{tem_mais}':   idx < lista.length ? 'sim' : 'nao'
});
Etapa 4. "Avançar Loop" (Regra Customizada · Python) → Ir para "Verificar Loop"
lista = bm.get('{lista_nfs}', [])
idx   = bm.get('{loop_index}') + 1

bm.done('avancou', {
    '{loop_index}': idx,
    '{item_atual}': lista[idx] if idx < len(lista) else '',
    '{tem_mais}':   'sim' if idx < len(lista) else 'nao'
})
Bypass para voltar ao início Na etapa "Avançar Loop", a Gestão de Erros e Exceções não é o caminho para voltar. O desvio de retorno é configurado dentro do fluxo normal. Use o campo Ir para da condição de rota (na etapa de Decisão ou onde ela estiver declarada) para criar o ciclo.

Loop while (aguardar condição)

Quando não há uma lista fixa. O loop deve continuar até que uma condição externa seja satisfeita, como um elemento aparecer na página ou um status mudar:

Padrão while: aguardar status "concluido"
// Etapa: Inicializar Espera
bm.done('init', {
  '{aguardando}': 'sim',
  '{tentativas}': 0
});

// Etapa: Verificar Status (Decisão 🔷, ou a mesma condição na etapa anterior/seguinte)
// Rota 1: {status_atual} == 'concluido'  → Prosseguir
// Rota 2: Number({tentativas}) >= 10               → Timeout
// Rota 3: true                                      → Aguardar e Tentar

// Etapa: Aguardar e Tentar (Regra Customizada) → Ir para "Verificar Status"
const t = Number(bm.get('{tentativas}')) + 1;
bm.done('aguardou', { '{tentativas}': t });
Use Atraso na Execução no cadastro do agente para adicionar um intervalo entre as iterações, evitando consultas excessivas ao sistema-alvo.

Para um intervalo entre uma consulta e outra só nesta etapa, sem código, use o Timer de Espera: na etapa "Aguardar e Tentar", configure alguns segundos (5, por exemplo). A espera roda depois do script da etapa, então cada volta do loop aguarda antes de a rota levar de novo a "Verificar Status". Se o intervalo precisa depender de uma condição, escreva a pausa no script, como em Timers → Aguardar em scripts.

Paginação de portal

Para percorrer múltiplas páginas de um sistema (lista paginada):

Padrão completo de paginação
// Etapa: Inicializar Paginação
bm.done('init', {
  '{pagina_atual}': 1,
  '{tem_proxima}': 'sim'
});

// Etapa: Verificar Próxima Página (Decisão 🔷, ou a mesma condição na etapa anterior/seguinte)
// Rota 1: {tem_proxima} == 'nao'  → Finalizar
// Rota 2: true                    → Navegar Página

// Etapa: Navegar Página
// URL: https://portal.com/lista?page={pagina_atual}

// Etapa: Extrair Dados da Página
// Mapeamento captura dados e verifica botão "Próxima"
// {tem_btn_proxima} = 'sim' ou 'nao'

// Etapa: Avançar Página (Regra Customizada) → Ir para "Verificar Próxima Página"
const paginaAtual = Number(bm.get('{pagina_atual}')) + 1;
bm.done('avancou', {
  '{pagina_atual}': paginaAtual,
  '{tem_proxima}': bm.get('{tem_btn_proxima}', 'nao')
});

Cuidados e limites

Limitador de Ações Cada iteração do loop consome ações do processo. Certifique-se de que o campo Limitador de Ações no cadastro do agente seja alto o suficiente para cobrir todas as iterações esperadas: número de itens × ações por iteração.
Limite de Tempo do Script numa etapa de laço Se a etapa que roda a cada iteração tem código, o Limite de Tempo do Script dela vale por iteração, e um valor folgado se multiplica pelo número de itens. Uma etapa que trava no item 40 com o padrão de 1 hora segura a execução por uma hora ali, e por mais uma a cada nova tentativa. Numa etapa de laço, use o tempo que um único item realmente precisa.