Skip to content

Instantly share code, notes, and snippets.

@trxcllnt
Last active August 29, 2015 14:01
Show Gist options
  • Save trxcllnt/f2a8d4d2fc50cd7da586 to your computer and use it in GitHub Desktop.
Save trxcllnt/f2a8d4d2fc50cd7da586 to your computer and use it in GitHub Desktop.
// Zone.create = Observable.create
// Zone#setCallback = Observable#forEach/Observable#subscribe
// Zone#then = Observable#map
// Zone#catch = Observable#catch
//
// A little stub of some zone examples that map 1-1 with Rx. Instead of a zone global,
// the "zone" object is passed in to the function we created the Zone with.
//
// This allows us to run multiple Zones in parallel, for example, if we want to await
// two run two asynchronous operations (say, a file-read and a network request) at the
// same time, then call the return callback when they're both done.
//
// Additionally, since Zone has a "complete" callback, a Zone itself can be thought of as
// an asynchronous collection of return values, or a long-running function with multiple
// return values.
//
// Disclaimer: I've spent about five minutes reading the "why-zone", description, and examples.
// I am sure I have missed very large, important points. But from the docs, it sounds like
// Reactive Extensions might be able to do everything you're trying to do, and it's been
// through six years of iteration by some of the best computer scientists on the planet.
// https://github.com/Reactive-Extensions/RxJS/
var readFileZone = Zone.create(function(zone) {
fs.readFile(function(err, x) {
if(err) {
zone.throw(err);
zone.complete();
} else {
zone.return(x);
}
});
});
readFileZone.setCallback({
return: function(x) {
console.log('yay I read my file.');
},
throw: function(err) {
console.error('error', err);
},
complete: function() {
console.log('all done');
}
});
var intervalZone = Zone.create(function(zone) {
var i = -1,
t = setInterval(function() {
zone.return(++i);
if(i > 9) {
clearInterval(t);
zone.complete();
}
}, 100);
});
intervalZone.setCallback({
return: function(i) {
console.log('got interval', i);
},
throw: function(e) {
console.error('what?');
},
complete: function() {
console.log('all done');
}
});
var numbers = [
'zero', 'one', 'two',
'three', 'four', 'five',
'six', 'seven', 'eight',
'nine', 'ten'
];
// This Zone starts its own separate `setInterval` context than
// the previous time we called `intervalZone.setCallback()`
var printIntervalZone = intervalZone.then(function(i) {
return numbers[i];
});
// call then's `setCallback,` which calls the intervalZone's `setCallback`
printIntervalZone.setCallback({
return: function(number) {
console.log('got number', number);
},
throw: function(e) {
console.error('nah');
},
complete: function() {
console.log('all done');
}
})
function Zone(setCallback) {
this.setCallback = setCallback;
}
Zone.create = function(setCallback) {
return new Zone(setCallback);
}
Zone.prototype.then = function(successCallback, errorCallback) {
var self = this;
return Zone.create(function(zone) {
return self.setCallback({
return: function(x) {
zone.return(successCallback(x));
},
throw: function(e) {
if(errorCallback) {
try {
var result = errorCallback(e);
zone.return(result);
} catch(e) {
zone.throw(e);
}
} else {
zone.throw(e);
}
},
complete: zone.complete.bind(zone)
})
});
};
Zone.prototype.catch = function(handler) {
var self = this;
return Zone.create(function(zone) {
return self.setCallback({
throw: function(e) {
try {
var result = handler(e);
zone.return(result);
} catch(e) {
zone.throw(e);
}
},
return: zone.return.bind(zone),
complete: zone.complete.bind(zone)
})
})
}
@piscisaureus
Copy link

The point of zones is: this should work, and throw in an async function should not crash node.
Does rx do this?

zone.create(function() {
  setTimeout(function() {
    throw new Error("Noo!")
  }, 1000);
}).setCallback(function(err) {
  console.log(err.message); // Should be "noo!"
});

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment