The task is to implement the Observable from.
The boilerplate code
function from(input) {
// your code here
}
from() creates an Observable from an array, an array-like object, a Promise, an iterable, or an observable-like object. It does not emit immediately and decides how to emit values based on the type of input.
If the input type is an observable-like object, the values flow directly to the new observer.
if (input && typeof input.subscribe === "function") {
return new Observable(observer => input.subscribe(observer));
}
If the input type is a promise, if it resolves, it emits one value and calls complete(). If it rejects, it calls error()
if (input && typeof input.then === "function") {
return new Observable(observer => {
let cancelled = false;
input.then(
value => {
if (!cancelled) {
observer.next(value);
observer.complete && observer.complete();
}
},
err => !cancelled && observer.error && observer.error(err)
);
return () => {
cancelled = true;
};
});
}
If the input type is iterable, each value is emitted via next in a synchronous loop. Call complete after iteration.
if (input && Symbol.iterator in Object(input)) {
return new Observable(observer => {
try {
for (const item of input) {
observer.next(item);
}
observer.complete && observer.complete();
} catch (err) {
observer.error && observer.error(err);
}
});
}
If the input type is a non-iterable array-like object
if (input && typeof input === "object" && typeof input.length === "number") {
return new Observable(observer => {
try {
for (let i = 0; i < input.length; i++) {
observer.next(input[i]);
}
observer.complete && observer.complete();
} catch (err) {
observer.error && observer.error(err);
}
});
}
If the input is invalid, throw an error
throw new TypeError("Input type not supported");
The final code
function from(input) {
// your code here
if(input && typeof input.subscribe === "function") {
return new Observable(observer => input.subscribe(observer))
}
if(input && typeof input.then === "function") {
return new Observable(observer => {
let cancelled = false;
input.then(
value => {
if(!cancelled) {
observer.next(value);
observer.complete && observer.complete()
}
},
err => !cancelled && observer.error && observer.error(err)
)
return () => {
cancelled = true;
}
})
}
if(input && Symbol.iterator in Object(input)) {
return new Observable(observer => {
try {
for(const item of input) {
observer.next(item);
}
observer.complete && observer.complete();
} catch (err) {
observer.error && observer.error(err);
}
})
}
if(input && typeof input === "object" && typeof input.length === "number") {
return new Observable(observer => {
try {
for(let i = 0; i < input.length; i++) {
observer.next(input[i]);
}
observer.complete && observer.complete()
} catch (err) {
observer.error && observer.error(err);
}
})
}
throw new TypeError("Input type not supported");
}
That's all folks!
Top comments (0)