Created
March 4, 2020 20:21
-
-
Save compulim/f9f9ca2227bdfc6ef8556877897da190 to your computer and use it in GitHub Desktop.
Intercept observable using middleware pattern
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
function interceptObservable(observable, middleware) { | |
return new Observable(observer => { | |
const initializedMiddleware = middleware(observer); | |
const subscription = observable.subscribe({ | |
close() { | |
observer.close(); | |
}, | |
error(err) { | |
observer.error(err); | |
}, | |
next(value) { | |
initializedMiddleware(value => observer.next(value))(value); | |
} | |
}); | |
return () => subscription.unsubscribe(); | |
}); | |
} | |
async function directLineWithMiddleware(directLine, activityMiddleware, connectionStatusMiddleware, postActivityMiddleware) { | |
await loadScript('https://unpkg.com/core-js@2/client/core.min.js'); | |
postActivityMiddleware = postActivityMiddleware && postActivityMiddleware(); | |
return { | |
...directLine, | |
activity$: activityMiddleware | |
? share(interceptObservable(directLine.activity$, activityMiddleware)) | |
: directLine.activity$, | |
connectionStatus$: connectionStatusMiddleware | |
? share(interceptObservable(directLine.connectionStatus$, connectionStatusMiddleware)) | |
: directLine.connectionStatus$, | |
postActivity: postActivityMiddleware | |
? activity => { | |
postActivityMiddleware(activity => directLine.postActivity(activity))(activity); | |
} | |
: directLine.postActivity.bind(directLine) | |
}; | |
} | |
function share(observable) { | |
const observers = []; | |
let subscription; | |
return new Observable(observer => { | |
observers.push(observer); | |
if (!subscription) { | |
subscription = observable.subscribe({ | |
complete: () => observers.forEach(observer => observer.complete()), | |
error: err => observers.forEach(observer => observer.error(err)), | |
next: value => observers.forEach(observer => observer.next(value)) | |
}); | |
} | |
return () => { | |
const index = observers.indexOf(observer); | |
~index && observers.splice(index, 1); | |
if (!observers.length) { | |
subscription.unsubscribe(); | |
subscription = null; | |
} | |
}; | |
}); | |
} | |
async function loadScript(src) { | |
return new Promise((resolve, reject) => { | |
const script = document.createElement('script'); | |
script.addEventListener('load', resolve); | |
script.addEventListener('error', reject); | |
script.setAttribute('src', src); | |
document.head.appendChild(script); | |
}); | |
} | |
window.WebChat.customizations = { | |
...window.WebChat.customizations, | |
patchProps: async props => { | |
const directLine = await directLineWithMiddleware(props.directLine, () => next => activity => { | |
if (!~(activity.text || '').indexOf('send failed')) { | |
return next(activity); | |
} | |
}); | |
return { | |
...props, | |
activityStatusMiddleware: () => next => args => { | |
const { sendState } = args; | |
if (sendState === 'sending') { | |
return 'Sending\u2026'; | |
} else if (sendState === 'send failed') { | |
return 'Send failed.'; | |
} | |
return next(args); | |
}, | |
directLine | |
}; | |
} | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment