function onMessage()

in ArticleTemplates/assets/js/modules/messenger.js [79:135]


function onMessage(event) {
    // We only allow communication with selected hosts
    if (allowedHosts.indexOf(event.origin) < 0) {
        return;
    }

    let data = getData(event.data);

    if (!isValidPayload(data)) {
        return;
    }

    if (Array.isArray(listeners[data.type]) && listeners[data.type].length) {
        // Because any listener can have side-effects (by unregistering itself),
        // we run the promise chain on a copy of the `listeners` array.
        // Hat tip @piuccio
        let promise = listeners[data.type].slice()
        // We offer, but don't impose, the possibility that a listener returns
        // a value that must be sent back to the calling frame. To do this,
        // we pass the cumulated returned value as a second argument to each
        // listener. Notice we don't try some clever way to compose the result
        // value ourselves, this would only make the solution more complex.
        // That means a listener can ignore the cumulated return value and
        // return something else entirely—life is unfair.
        // We don't know what each callack will be made of, we don't want to.
        // And so we wrap each call in a promise chain, in case one drops the
        // occasional fastdom bomb in the middle.
        .reduce(function (promise, listener) {
            return promise.then(function promiseCallback(ret) {
                var iframe = getIframe(data);
                if (!iframe) {
                    throw new Error(formatError(error500, 'iframe element not found'));
                }
                var thisRet = listener(data.value, ret, iframe);
                return thisRet === undefined ? ret : thisRet;
            });
        }, Promise.resolve(true));

        return promise.then(function (response) {
            respond(null, response);
        }).catch(function (ex) {
            respond(formatError(error500, ex), null);
        });
    } else if (typeof listeners[data.type] === 'function') {
        // We found a persistent listener, to which we just delegate
        // responsibility to write something. Anything. Really.
        listeners[data.type](respond, data.value, getIframe(data));
    } else {
        // If there is no routine attached to this event type, we just answer
        // with an error code
        respond(formatError(error405, data.type), null);
    }

    function respond(error, result) {
        postMessage({ id: data.id, error: error, result: result }, event.source, event.origin);
    }
}