Async await para recuperar informação de dataset

É possível usar async e await numa pesquisa de dataset?

(Isto, abaixo, definitivamente não funciona, porque já fere as regras de sintaxe do javascript. Forcei apenas para dar uma ideia do que estou perguntando.)


async function fAsyncAwait(){
 return await  datasetFactory.getDataset("ds_ucrg_pessoas",null,null,null);
}

É possível?

Mausim,

O método DatasetFactory.getDataset não retorna uma Promise, por isso não é possível usar async/await. Ele até fornece uma assinatura pra trabalhar sem ser de forma assíncrona, mas sempre tive erros com ele.

Eu fiz uma wrapper pra isso.

Lembrando que é necessário importar a vcXMLRPC.js e isso só funciona no navegador, pois essa nova sintaxe não é aceita pelo Rhino na hora de converter pra Java e assim executar no back-end do Fluig.


/**
 * Pega um dataset
 *
 * Wrapper para tornar a DatasetFactory.getDataset em Promise.
 *
 * @param {string} dataset Nome do Dataset
 * @param {string[]} fields Campos para retornar (pode ser null pra retornar todos)
 * @param {Constraint[]} constraints Os filtros a aplicar ou null se não filtrar nada
 * @param {string[]} sorters Campos para ordenar ou null para não ordenar. Pode colocar ;desc no campo para ordenar decrescente
 * @returns {Promise} Resolve com o objeto dataset {columns: string[], values: string[]}
 */
function getDataset(dataset, fields, constraints, sorters) {
    return new Promise(function (resolve, reject) {
        DatasetFactory.getDataset(
            dataset,
            fields,
            constraints,
            sorters,
            {
                success: data => resolve(data),
                error: () => reject(arguments)
            }
        );
    });
}

Aí consigo usar normalmente o async/await. Só lembrando que ao usar async/await é bom usar try...catch.


async function asyncExample() {
    try {
        let attachments = await getDataset(
            "ds_process_attachments_files", 
            null, 
            [DatasetFactory.createConstraint("processId", agenda.idprocesso, agenda.idprocesso, ConstraintType.MUST)],
            null
        ).values;

        // resto do código

    } catch (error) {
        console.error(error);
    }
}

E também consigo trabalhar normalmente com as Promises:


getDataset(
    "ds_reuniao_direx",
    ["processInstanceId", "cardDocumentId", "type", "sponsor", "subject", "goal"],
    [
        DatasetFactory.createConstraint("meetingName", "", "", ConstraintType.MUST)
    ],
    null
)
.then(dataset => dataset.values)
.then(function (data) {
    // resto do código
})
.catch(error => console.log(error));

Elegante e eficiente. Obrigado, Bruno

Além da resposta do Bruno, muito bem elaborada, enquanto eu não tinha a resposta da minha pergunta, continuei tentando e achei uma forma rudimentar para atender minha necessidade que funcionou, mas, claro, não tão bem quanto a do Bruno. Talvez sirva para quem desejar fazer testes.


jQuery(document).ready(function (){

 jQuery("#idBtnTeste").click(function (){

   fAsyncPesquisaDataset().then(function(resultado) {

      for (i=0;i<resultado.values.length;i++){
       console.log(resultado.values[i].RAZAO_SOCIAL);
      }//for

   }).then(function (){
       jQuery("#idTxt").val("Terminou!");
   });
 });//idBtnTeste click
}//ready

async function fAsyncPesquisaDataset() { 
   let c1 = DatasetFactory.createConstraint("ANO_MES","2019%","2019%",ConstraintType.MUST,true);

   let arrayConstraints =new Array(c1);
   return resultado = await Promise.resolve(
   DatasetFactory.getDataset('ds_ucrg_evolucao_desp',null,arrayConstraints, 
   ['RAZAO_SOCIAL'])
 );//promise

}//fAsyncPesquisaDataset

Sempre que tentei usar a DatasetFactory.getDataset sem passar o objeto de callback (usando de forma síncrona) eu tive problemas e aí você a chamou de forma síncrona, mas a jogou dentro de uma Promise.resolve. Um problema é que a JQuery trabalha com o $.Deferred que não é compatível com Promise. Eu tive muitos problemas ao tentar exibir uma tela de loading durante a execução da DatasetFactory.getDataset desta forma. Dava erros de só exibir o loading quando terminava de carregar o dataset, mas aí já fechava o loading no mesmo momento. Por isso fiz a wrapper, assim garanto a execução correta.

Aliás, a DatasetFactory.getDataset quando usada sem o objeto de callback faz uma chamada AJAX passando a opção de ser síncrona, porém isso está descontinuado (deprecated) e o navegador sempre dá um alerta informando o problema. Talvez por isso ela tenha um comportamento ruim. Acredito que logo a TOTVS terá que rever o código da biblioteca vcXMLRPC.js. Mas só pra deixar mais claro: quando é feita a requisição de forma síncrona tudo fica travado até a requisição terminar e isso pode impactar na execução das outras coisas. Por isso eu tive os problemas ao tentar usar o Loading.