2015-03-11 12 views
7

Dato il seguente task gulp, perché dovrei ricevere il seguente errore?Perché dovrei ricevere "callback di completamento attività chiamato troppe volte" in gulp?

Error: task completion callback called too many times

function myTask(options, cb) { // cb is the gulp cb 
    var serverInstance = http.createServer(dispatch({ /*routes*/ })); 

    serverInstance.listen(options.port, function() { 
    cb(); // Stack trace identifies this line as throwing the error 
    }); 
} 

function partial(fn) { 
    var args = Array.prototype.slice.call(arguments, 1); 

    return function() { 
     return fn.apply(this, args.concat(Array.prototype.slice.call(arguments))); 
    }; 
} 

gulp.task('task-name', ['task-dependency'], partial(myTask, { port: 8080 })); 

Edit:

La seguente modifica rende il lavoro (la mia domanda rimane ancora però):

gulp.task('task-name', ['task-dependency'], function(cb) { 
    partial(myTask, { port: 8080 })(cb); 
}); 
+0

Non ho molta familiarità con Gulp, ma non è previsto per l'esecuzione di build? Sembra che tu stia usando per avviare un server. E se accedi a quel server più di una volta, il callback 'cb() 'sarà chiamato più di una volta. – JLRishe

+0

Sì, al termine di questa attività di build, viene avviato un server che consegnerà l'applicazione a scopo di test sul computer di uno sviluppatore. – Ben

+0

@JLRishe il callback fornito viene richiamato una sola volta quando l'evento di ascolto viene generato dal server (IIUC) https://nodejs.org/api/http.html#http_server_listen_port_hostname_backlog_callback – Ben

risposta

4

Questo perché sorso utilizza euristica (compreso il valore di ritorno del callback e se accetta un parametro di callback) per rilevare attività asincrone vs sincronizzazione e le tratta in modo diverso di conseguenza. La mia funzione parziale restituisce una funzione senza parametri dichiarati che ingannava il ragionamento pensando che fosse sincrono quando era asincrono.

La modifica di partial per restituire una funzione con un singolo parametro denominato ha risolto il problema.

//... 
return function(cb) { 
    return fn.apply(this, args.concat(slice.call(arguments))); 
}; 
//... 
+1

Se si utilizza '.bind()' per l'applicazione della funzione parziale, verrà creata una funzione con l'arità corretta: '(funzione myTask (opzioni, cb) {}). Bind (null, {port: 8080}). lunghezza === 1' – JLRishe

+0

Buon punto. La mia originaria elusione di legare era perché non volevo influenzare il ricevitore della funzione. Separatamente, esiste un meccanismo per modificare l'arità di una funzione in fase di esecuzione senza utilizzare bind (o eval)? Ad esempio, la lunghezza è scrivibile? Modifica: no 'length' non è scrivibile – Ben

+2

AFAIK, l'unica altra opzione è usare il costruttore di funzioni, ma è piuttosto hacky. La sintassi non fornisce alcuna opzione pulita per indicare in modo dinamico il numero di parametri di una funzione creata. lodash '_.bind',' _.curry' e '_.partial' restituiscono tutte le funzioni con arity 0. – JLRishe

Problemi correlati