und andere Versprechungen
Stefan von der Krone
Das Problem
function getUser(name) {
var sql = 'SELECT * FROM users WHERE name=?';
var user = query(sql, name); // <- blocking
if (!user) throw new Error('no user!');
return user;
}
Das Problem
function getUser(name, callback) {
var sql = 'SELECT * FROM users WHERE name=?'
query(sql, name, function (error, user) {
if (error) {
callback(error);
} else if (!user) {
callback(new Error('no user!'));
} else {
callback(null, user);
}
});
};
Das Problem
Global State Var(s)?
The NodeJS Way?
Wrapper?
fs.readFile(
filename, 'utf8', function (err, res){
if (err) return callback(err);
callback(null, JSON.parse(res));
}
);
var res, err;
function onFinished() {
if (err) { /* handle error */ }
else { /* handle result */ }
}
// ... do awesome stuff with 'onFinished'
// as final callback ...
doAwesomeStuffWithManyInnerCallbacks( {
onComplete: function( result ) {
// handle result
},
onError: function( error ) {
// handle error
}
} );
Das Problem
function getUser(name, callback) {
var sql = 'SELECT * FROM users WHERE name=?';
query(sql, nome, function (error, user) {
// Nobody can catch this error!
if (error) throw error; // <- BAD
// Nobody gets this return value!
return user;
});
}
Das Problem
Quo Vadis?
Promises / Futures
Ein Future oder ein Promise bezeichnet in der Programmierung einen Platzhalter (Proxy) für ein Ergebnis, das noch nicht bekannt ist, meist weil seine Berechnung noch nicht abgeschlossen ist. (Wikipedia)
Die Lösung
getUser('sdk', function (error, user) {
// ...
});
// becomes
getUser('sdk')
.then(function (user) {
// ...
}, function (error) {
// ...
});
try {
var user = getUser('sdk');
if (!user)
throw new Error('no user!');
var name = user.name;
} catch (e) { /* handle error */ }
// becomes
getUser('sdk')
.then(function (user) {
return user.name;
})
.then(function(name) {
// do some awesome stuff
}, function(reason) {
// handle error
});
Die Lösung
var user = getUser('thunderkrown');
var tweets = getNewTweets(user);
updateTimeline(tweets);
// using callbacks
getUser('thunderkrown', function (user) {
getNewTweets(user, function (tweets) {
updateTimeline(tweets);
});
});
// using promises
getUser('thunderkrown')
.then(getNewTweets)
.then(updateTimeline);
var user = getUser('thunderkrown');
var tweets = getNewTweets(user);
updateTimeline(tweets);
// using callbacks
getUser('thunderkrown', function (user) {
getNewTweets(user, function (tweets) {
updateTimeline(tweets);
});
});
// using promises
getUser('thunderkrown')
.then(getNewTweets)
.then(updateTimeline, onError);
Q($.ajax(/* ... */));
Promises in Angular
var deferred = $q.defer();
// bei Erfolg
deferred.resolve( result );
// bei Fehler
deferred.reject( error );
return deferred.promise;
return $q(function(resolve, reject) {
// bei Erfolg
resolve( result );
// bei Fehler
reject( error );
});
seit Angular 1.3
Promises in Angular
App.config( function( $stateProvider, $urlRouterProvider ) {
$stateProvider
.state( "someState", {
url: "/some-state",
templateUrl: "some-state.html",
controller: function($scope, data) {},
resolve: {
data: function() {
// returns a ($q-)Promise
return loadData()
}
}
} );
} );
Promises in Angular
Promises sind monadische Daten-Strukturen
Theorie-Exkurs
~Abstrakter Datentyp, der einen Ausdruck in einen Kontext kapselt.~