Вызовы функций секвенирования в javascript - единственные ли обратные вызовы?
Я читаю различные темы, например эту.
Но это действительно ускользает от меня, как сделать следующее:
У меня есть 4 функции, и я хочу, чтобы они выполнялись последовательно. Обратите внимание, что они в неправильном порядке, чтобы понять мою точку зрения. Я хочу, чтобы результат, который будет выводить "1, 2, 3, 4'
function firstFunction(){
// some very time consuming asynchronous code...
console.log('1');
}
function thirdFunction(){
// definitely dont wanna do this until secondFunction is finished
console.log('3');
}
function secondFunction(){
// waits for firstFunction to be completed
console.log('2');
}
function fourthFunction(){
// last function, not executed until the other 3 are done.
console.log('4');
}
Я пытался выяснить обратные вызовы, но теряюсь:(
Разве нет простого способа сделать это? Как зацикливание массива...
5 ответов
Это отличный шанс начать использовать jQuery Deferred.
Помимо решения на основе обратных вызовов, код читабелен, гибок и легко обслуживается.
http://jsfiddle.net/zerkms/zJhph/
function firstFunction(){
var d = $.Deferred();
// some very time consuming asynchronous code...
setTimeout(function() {
console.log('1');
d.resolve();
}, 1000);
return d.promise();
}
function thirdFunction(){
var d = $.Deferred();
// definitely dont wanna do this until secondFunction is finished
setTimeout(function() {
console.log('3');
d.resolve();
}, 1000);
return d.promise();
}
function secondFunction(){
var d = $.Deferred();
setTimeout(function() {
console.log('2');
d.resolve();
}, 1000);
return d.promise();
}
function fourthFunction(){
var d = $.Deferred();
// last function, not executed until the other 3 are done.
setTimeout(function() {
console.log('4');
d.resolve();
}, 1000);
return d.promise();
}
firstFunction().pipe(secondFunction).pipe(thirdFunction).pipe(fourthFunction);
PS: в качестве примера асинхронного кода я использовал setTimeout
, Главное, что в конце асинхронной части нужно вызвать d.resolve()
продолжить цепочки методов.
Дополнительное чтение: http://joseoncode.com/2011/09/26/a-walkthrough-jquery-deferred-and-promise/
Идея состоит в том, что вы должны сделать что-то вроде следующего, чтобы после запуска первой функции она знала, что нужно запускать, в отличие от того, чтобы вам приходилось разбираться с этим самостоятельно вне функции:
function firstFunction(callback){
// some very time consuming asynchronous code...
console.log('1');
return callback(function(){
alert("Second function finished.");
return true;
});
}
function secondFunction(callback){
// waits for firstFunction to be completed
console.log('2');
return callback();
}
firstFunction(secondFunction);
Также посмотрите вверх .apply()
а также .call()
,
Если я использую обратные вызовы, мое рабочее решение теперь выглядит так:
one(two);
function one(callb){
console.log('1');
callb(three);
}
function four(){
console.log('4');
}
function two(callb){
console.log('2');
callb(four);
}
function three(callb){
console.log('3');
callb();
}
Я нахожу это отвратительным. Как я должен отслеживать этот материал, если есть более 2-3 последовательностей? Shudder...
Прошло много времени, и я кое-что заметил deferreds
в документации JQuery, в частности, when
основная функция API.
$.when( $.ajax("test.aspx") ).then(function(ajaxArgs){
alert(ajaxArgs[1]); /* ajaxArgs is [ "success", statusText, jqXHR ] */
});
Пример кода взят с http://jqapi.com/
Я поиграл с Обещанием, Последовательностью, Исключением, Обратным вызовом, чтобы понять, как это работает, и, наконец, сделал этот код.
Вызовите функции с обратным вызовом и отправьте результат в качестве параметра другой функции по очереди и получите ошибки перехвата.
function firstFunction(par) {
return new Promise(function (resolve, reject) {
console.log("start " + par);
setTimeout(function (par) {
console.log(par);
resolve(par + 1);
}, 1000, par);
});
}
function secondFunction(par) {
return new Promise(function (resolve, reject) {
console.log("start " + par);
setTimeout(function (par) {
console.log(par);
try{
throw "Let's make an error...";
}
catch(err)
{
reject(err);
}
resolve(par + 1);
}, 1000, par);
})
}
function thirdFunction(par) {
return new Promise(function (resolve, reject) {
console.log("start " + par);
setTimeout(function (par) {
console.log(par);
resolve(par + 1);
}, 1000, par);
});
}
function CatchError(error) {
console.log("Exception: " + error);
}
//Break all chain in second function
function ChainBrake() {
firstFunction(1)
.then(secondFunction)
.then(thirdFunction)
.catch(CatchError);
}
//Log error and continue executing chain
function ChainContinue() {
firstFunction(1)
.catch(CatchError)
.then(secondFunction)
.catch(CatchError)
.then(thirdFunction)
.catch(CatchError);
}