visualización renderizado recursos quitar que los eliminar elimina contenido como bloqueo bloqueen bloquean bloquea javascript node.js

javascript - renderizado - ¿Cómo hacer solicitudes repetidas hasta que uno tenga éxito sin bloquear en el nodo?



quitar el javascript que bloquea el renderizado de contenido wordpress (7)

Tengo una función que toma un parámetro y una devolución de llamada. Se supone que debe hacer una solicitud a una API remota y obtener cierta información basada en el parámetro. Cuando recibe la información, necesita enviarla a la devolución de llamada. Ahora, la API remota a veces no puede proporcionar. Necesito que mi función siga intentando hasta que logre hacerlo y luego llame a la devolución de llamada con los datos correctos.

Actualmente, tengo el código de abajo dentro de la función, pero creo que eso me gusta while ( !done ); no es el código de nodo adecuado.

var history = {}; while (true) { var done = false; var retry = true; var req = https.request(options, function(res) { var acc = ""; res.on("data", function(msg) { acc += msg.toString("utf-8"); }); res.on("end", function() { done = true; history = JSON.parse(acc); if (history.success) { retry = false; } }); }); req.end(); while (!done); if (!retry) break; } callback(history);

¿Cómo lo hago de la manera correcta?


¿Es esto lo que estas tratando de hacer?

var history = {}; function sendRequest(options, callback) { var req = https.request(options, function (res) { var acc = ""; res.on("data", function (msg) { acc += msg.toString("utf-8"); }); res.on("end", function () { history = JSON.parse(acc); if (history.success) { callback(history); } else { sendRequest(options, callback); } }); }); req.end(); } sendRequest(options, callback);


Definitivamente no es el camino a seguir, mientras que (! Hecho); entrará en un bucle duro y ocupará toda su CPU.

En su lugar, podría hacer algo como esto (sin probar y es posible que desee implementar un back-off de algún tipo):

function tryUntilSuccess(options, callback) { var req = https.request(options, function(res) { var acc = ""; res.on("data", function(msg) { acc += msg.toString("utf-8"); }); res.on("end", function() { var history = JSON.parse(acc); //<== Protect this if you may not get JSON back if (history.success) { callback(null, history); } else { tryUntilSuccess(options, callback); } }); }); req.end(); req.on(''error'', function(e) { // Decide what to do here // if error is recoverable // tryUntilSuccess(options, callback); // else // callback(e); }); } // Use the standard callback pattern of err in first param, success in second tryUntilSuccess(options, function(err, resp) { // Your code here... });


Encontré la respuesta de Dmitry usando la biblioteca de utilidad asíncrona muy útil y la mejor respuesta.

Esta respuesta expande su ejemplo a una versión de trabajo que define la función apiMethod y le pasa un parámetro. Iba a agregar el código como un comentario, pero una respuesta por separado es más clara.

const async = require(''async''); const apiMethod = function(uri, callback) { try { // Call your api here (or whatever thing you want to do) and assign to result. const result = ... callback(null, result); } catch (err) { callback(err); } }; const uri = ''http://www.test.com/api''; async.retry( { times: 5, interval: 200 }, function (callback) { return apiMethod(uri, callback) }, function(err, result) { if (err) { throw err; // Error still thrown after retrying N times, so rethrow. } });

Vuelva a intentar la documentación: https://caolan.github.io/async/docs.html#retry

Tenga en cuenta que una alternativa a llamar a apiMethod (uri, callback) en la tarea es usar async.apply:

async.retry( {times: 5, interval: 200}, async.apply(task, dir), function(err, result) { if (err) { throw err; // Error still thrown after retrying N times, so rethrow. } });

Espero que esto proporcione una buena solución para copiar / pegar la placa de caldera para alguien.


He resuelto este problema utilizando el módulo de retry .

Ejemplo:

var retry = require(''retry''); // configuration var operation = retry.operation({ retries: 2, // try 1 time and retry 2 times if needed, total = 3 minTimeout: 1 * 1000, // the number of milliseconds before starting the first retry maxTimeout: 3 * 1000 // the maximum number of milliseconds between two retries }); // your unreliable task var task = function(input, callback) { Math.random() > 0.5 ? callback(null, ''ok'') // success : callback(new Error()); // error } // define a function that wraps our unreliable task into a fault tolerant task function faultTolerantTask(input, callback) { operation.attempt(function(currentAttempt) { task(input, function(err, result) { console.log(''Current attempt: '' + currentAttempt); if (operation.retry(err)) { // retry if needed return; } callback(err ? operation.mainError() : null, result); }); }); } // test faultTolerantTask(''some input'', function(err, result) { console.log(err, result); });


No hay necesidad de reinventar la rueda ... puede usar una popular biblioteca de utilidades asíncronas, en este caso el método de "reintento".

async.retry(3, apiMethod, function(err, result) { // do something with the result });

página asíncrona de GitHub

async.retry docs


Podrías probar algo en las siguientes líneas. Estoy escribiendo una idea general, debe reemplazar trySomething con su solicitud HTTP.

function keepTrying(onSuccess) { function trySomething(onSuccess, onError) { if (Date.now() % 7 === 0) { process.nextTick(onSuccess); } else { process.nextTick(onError); } } trySomething(onSuccess, function () { console.log(''Failed, retrying...''); keepTrying(onSuccess); }); } keepTrying(function () { console.log(''Succeeded!''); });

Espero que esto ayude.


Una biblioteca llamada Flashheart también es una alternativa adecuada. Es un cliente de descanso diseñado para ser fácil de usar y admite reintentos.

Por ejemplo, configure Flashheart para que vuelva a intentarlo 10 veces, con un retraso de 500 ms entre las solicitudes:

const client = require(''flashheart'').createClient({ retries: 10, retryTimeout: 500 }); const url = "https://www.example.com/"; client.get(url, (err, body) => { if (err) { console.error(''handle error: '', err); return; } console.log(body); });

Para obtener más información, consulte la documentación: https://github.com/bbc/flashheart

Descargo de responsabilidad: He contribuido a esta biblioteca.