/* eslint-disable @lwc/lwc/no-async-operation */
import { LightningElement, wire, api } from 'lwc';
import { loadScript } from 'lightning/platformResourceLoader';
import PP from '@salesforce/resourceUrl/penpal'
import getVisualforceDomainURL from '@salesforce/apex/LC_VisualforceDomainController.getVisualforceDomainURL';
export default class Api extends LightningElement {
_penpal = {};
penpalInitialized = false;
iframeSrc = '';
@wire(getVisualforceDomainURL) wiredDomainUrl({ error, data }) {
if (data) {
this.iframeSrc = data + '/apex/LC_APIPage';
console.log(this.iframeSrc);
this.initializePenpal();
} else if (error) {
console.error('LWC_API: error getting Visualforce Domain URL', error);
this.iframeSrc = undefined;
}
}
connectedCallback() {
Promise.all([
loadScript(this, PP)
]).then(() => { });
}
initializePenpal() {
let initialized = this.penpalInitialized;
var self = this;
// Since the iframe source is calculated asynchronously,
// we listen to the component's render events and each time
// check if the iframe is ready, and if so, then we initialize
// penpal to connect this component to the iframe.
// Since we only want to do this once, we also set the initialized flag.
if (!initialized) {
const container = this.template.querySelector('div');
const iframeElmt = document.createElement('iframe');
iframeElmt.src = this.iframeSrc;
container.appendChild(iframeElmt);
if (iframeElmt != null) {
this.penpalInitialized = true;
// eslint-disable-next-line no-undef
const connection = Penpal.connectToChild({
// The iframe to which a connection should be made
iframe: iframeElmt
});
this._penpal.connection = connection;
connection.promise.then(function (child) {
// Cache a reference to the child so that we can
// use it in the restRequest/fetchRequest methods,
// as well as be able to destroy it when this component unrenders.
console.log(child);
self._penpal.child = child[0];child;
}).catch(function (err) {
console.error('LWC_API: Error establishing connection to iframe', err);
this.penpalInitialized = false;
});
} // else, iframe source is empty, keep waiting
}
}
// Makes a Salesforce REST API request and returns a promise that resolves to the response.
@api restRequest(request) {
var self = this;
var defaultRequest = {
'method': 'get'
};
var defaultHeaders = {
'Content-Type': 'application/json'
};
request = Object.assign({}, defaultRequest, request);
request.headers = Object.assign({}, defaultHeaders, request.headers);
return this.getPenpalChild().then(function (child) {
return self.makePenpalRequest('rest', child, request);
});
}
@api fetchRequest(request) {
return this.getPenpalChild().then(function (child) {
return this.makePenpalRequest('fetch', child, request);
});
}
// ------------------------------------------------------------
/**
* For internal use.
* Returns a promise waiting for the parent-child postmate handshake to complete
* then resolves with reference to the postmate child for making requests.
*/
getPenpalChild() {
var child;
var self = this;
var timerId;
var timeout = 10000; // ten seconds
var pollFrequency = 500; // half a second
var startTime = new Date().getTime();
var endTime = startTime + timeout;
return new Promise(function (resolve, reject) {
child = self._penpal.child;
if (child) {
resolve(child);
} else {
// all time values in milliseconds
timerId = setInterval(function () {
child = this._penpal.child;
if (child) {
// parent-child postmate handshake now complete
clearInterval(timerId);
resolve(child);
} else {
// check if we have exceeded our timeout
let currentTime = new Date().getTime();
if (currentTime > endTime) {
clearInterval(timerId);
reject('LWC_API: Timeout trying to establish connection to iframe');
}
// else, keep polling
}
}, pollFrequency);
}
});
}
/**
* For internal use.
* Returns a promise waiting for the parent-child postmate request to complete
* then resolves with response from the child iframe.
*/
makePenpalRequest(requestType, child, request) {
var p;
if (requestType === 'rest') {
console.log('makePenpalRequest');
console.log(child);
console.log(child.restRequest);
p = child.restRequest(request);
} else if (requestType === 'fetch') {
p = child.fetchRequest(request);
} else {
p = Promise.resolve({
success: false,
data: 'LWC_API: Invalid request type: ' + requestType
});
}
console.log('makePenpalRequest');
return p.then(function (response) {
console.log(response);
if (response.success) {
return response.data;
}
throw new Error(response.data);
});
}
disconnectedCallback() { // unrender
// this.superUnrender();
// When component unrenders then cleanup penpal
// resources by destroying the connection and nulling out
// the helper's cached reference to the connection and child.
// This ensures that the helper.handleXyzRequest(..) methods
// wait appropriately for the new parent-child handshake to complete
// when this component is re-initialized and scripts are loaded.
if (this._penpal && this._penpal.connection) {
this._penpal.connection.destroy();
this._penpal = {};
}
}
}
/* eslint-disable @lwc/lwc/no-async-operation */
import { LightningElement, wire, api } from 'lwc';
import { loadScript } from 'lightning/platformResourceLoader';
import PP from '@salesforce/resourceUrl/penpal'
import getVisualforceDomainURL from '@salesforce/apex/LC_VisualforceDomainController.getVisualforceDomainURL';
export default class Api extends LightningElement {
_penpal = {};
penpalInitialized = false;
iframeSrc = '';
@wire(getVisualforceDomainURL) wiredDomainUrl({ error, data }) {
if (data) {
this.iframeSrc = data + '/apex/LC_APIPage';
console.log(this.iframeSrc);
this.initializePenpal();
} else if (error) {
console.error('LWC_API: error getting Visualforce Domain URL', error);
this.iframeSrc = undefined;
}
}
connectedCallback() {
Promise.all([
loadScript(this, PP)
]).then(() => { });
}
initializePenpal() {
let initialized = this.penpalInitialized;
var self = this;
// Since the iframe source is calculated asynchronously,
// we listen to the component's render events and each time
// check if the iframe is ready, and if so, then we initialize
// penpal to connect this component to the iframe.
// Since we only want to do this once, we also set the initialized flag.
if (!initialized) {
const container = this.template.querySelector('div');
const iframeElmt = document.createElement('iframe');
iframeElmt.src = this.iframeSrc;
container.appendChild(iframeElmt);
if (iframeElmt != null) {
this.penpalInitialized = true;
// eslint-disable-next-line no-undef
const connection = Penpal.connectToChild({
// The iframe to which a connection should be made
iframe: iframeElmt
});
this._penpal.connection = connection;
connection.promise.then(function (child) {
// Cache a reference to the child so that we can
// use it in the restRequest/fetchRequest methods,
// as well as be able to destroy it when this component unrenders.
self._penpal.child = child[0];
}).catch(function (err) {
console.error('LWC_API: Error establishing connection to iframe', err);
this.penpalInitialized = false;
});
} // else, iframe source is empty, keep waiting
}
}
// Makes a Salesforce REST API request and returns a promise that resolves to the response.
@api restRequest(request) {
var self = this;
var defaultRequest = {
'method': 'get'
};
var defaultHeaders = {
'Content-Type': 'application/json'
};
request = Object.assign({}, defaultRequest, request);
request.headers = Object.assign({}, defaultHeaders, request.headers);
return this.getPenpalChild().then(function (child) {
return self.makePenpalRequest('rest', child, request);
});
}
@api fetchRequest(request) {
return this.getPenpalChild().then(function (child) {
return this.makePenpalRequest('fetch', child, request);
});
}
// ------------------------------------------------------------
/**
* For internal use.
* Returns a promise waiting for the parent-child postmate handshake to complete
* then resolves with reference to the postmate child for making requests.
*/
getPenpalChild() {
var child;
var self = this;
var timerId;
var timeout = 10000; // ten seconds
var pollFrequency = 500; // half a second
var startTime = new Date().getTime();
var endTime = startTime + timeout;
return new Promise(function (resolve, reject) {
child = self._penpal.child;
if (child) {
resolve(child);
} else {
// all time values in milliseconds
timerId = setInterval(function () {
child = this._penpal.child;
if (child) {
// parent-child postmate handshake now complete
clearInterval(timerId);
resolve(child);
} else {
// check if we have exceeded our timeout
let currentTime = new Date().getTime();
if (currentTime > endTime) {
clearInterval(timerId);
reject('LWC_API: Timeout trying to establish connection to iframe');
}
// else, keep polling
}
}, pollFrequency);
}
});
}
/**
* For internal use.
* Returns a promise waiting for the parent-child postmate request to complete
* then resolves with response from the child iframe.
*/
makePenpalRequest(requestType, child, request) {
var p;
if (requestType === 'rest') {
console.log('makePenpalRequest');
console.log(child);
console.log(child.restRequest);
p = child.restRequest(request);
} else if (requestType === 'fetch') {
p = child.fetchRequest(request);
} else {
p = Promise.resolve({
success: false,
data: 'LWC_API: Invalid request type: ' + requestType
});
}
console.log('makePenpalRequest');
return p.then(function (response) {
console.log(response);
if (response.success) {
return response.data;
}
throw new Error(response.data);
});
}
disconnectedCallback() { // unrender
// this.superUnrender();
// When component unrenders then cleanup penpal
// resources by destroying the connection and nulling out
// the helper's cached reference to the connection and child.
// This ensures that the helper.handleXyzRequest(..) methods
// wait appropriately for the new parent-child handshake to complete
// when this component is re-initialized and scripts are loaded.
if (this._penpal && this._penpal.connection) {
this._penpal.connection.destroy();
this._penpal = {};
}
}
}
/* eslint-disable @lwc/lwc/no-async-operation */
import { LightningElement, wire, api } from 'lwc';
import { loadScript } from 'lightning/platformResourceLoader';
import PP from '@salesforce/resourceUrl/penpal'
import getVisualforceDomainURL from '@salesforce/apex/LC_VisualforceDomainController.getVisualforceDomainURL';
export default class Api extends LightningElement {
_penpal = {};
penpalInitialized = false;
iframeSrc = '';
@wire(getVisualforceDomainURL) wiredDomainUrl({ error, data }) {
if (data) {
this.iframeSrc = data + '/apex/LC_APIPage';
console.log(this.iframeSrc);
this.initializePenpal();
} else if (error) {
console.error('LWC_API: error getting Visualforce Domain URL', error);
this.iframeSrc = undefined;
}
}
connectedCallback() {
Promise.all([
loadScript(this, PP)
]).then(() => { });
}
initializePenpal() {
let initialized = this.penpalInitialized;
var self = this;
// Since the iframe source is calculated asynchronously,
// we listen to the component's render events and each time
// check if the iframe is ready, and if so, then we initialize
// penpal to connect this component to the iframe.
// Since we only want to do this once, we also set the initialized flag.
if (!initialized) {
const container = this.template.querySelector('div');
const iframeElmt = document.createElement('iframe');
iframeElmt.src = this.iframeSrc;
container.appendChild(iframeElmt);
if (iframeElmt != null) {
this.penpalInitialized = true;
// eslint-disable-next-line no-undef
const connection = Penpal.connectToChild({
// The iframe to which a connection should be made
iframe: iframeElmt
});
this._penpal.connection = connection;
connection.promise.then(function (child) {
// Cache a reference to the child so that we can
// use it in the restRequest/fetchRequest methods,
// as well as be able to destroy it when this component unrenders.
console.log(child);
self._penpal.child = child;
}).catch(function (err) {
console.error('LWC_API: Error establishing connection to iframe', err);
this.penpalInitialized = false;
});
} // else, iframe source is empty, keep waiting
}
}
// Makes a Salesforce REST API request and returns a promise that resolves to the response.
@api restRequest(request) {
var self = this;
var defaultRequest = {
'method': 'get'
};
var defaultHeaders = {
'Content-Type': 'application/json'
};
request = Object.assign({}, defaultRequest, request);
request.headers = Object.assign({}, defaultHeaders, request.headers);
return this.getPenpalChild().then(function (child) {
return self.makePenpalRequest('rest', child, request);
});
}
@api fetchRequest(request) {
return this.getPenpalChild().then(function (child) {
return this.makePenpalRequest('fetch', child, request);
});
}
// ------------------------------------------------------------
/**
* For internal use.
* Returns a promise waiting for the parent-child postmate handshake to complete
* then resolves with reference to the postmate child for making requests.
*/
getPenpalChild() {
var child;
var self = this;
var timerId;
var timeout = 10000; // ten seconds
var pollFrequency = 500; // half a second
var startTime = new Date().getTime();
var endTime = startTime + timeout;
return new Promise(function (resolve, reject) {
child = self._penpal.child;
if (child) {
resolve(child);
} else {
// all time values in milliseconds
timerId = setInterval(function () {
child = this._penpal.child;
if (child) {
// parent-child postmate handshake now complete
clearInterval(timerId);
resolve(child);
} else {
// check if we have exceeded our timeout
let currentTime = new Date().getTime();
if (currentTime > endTime) {
clearInterval(timerId);
reject('LWC_API: Timeout trying to establish connection to iframe');
}
// else, keep polling
}
}, pollFrequency);
}
});
}
/**
* For internal use.
* Returns a promise waiting for the parent-child postmate request to complete
* then resolves with response from the child iframe.
*/
makePenpalRequest(requestType, child, request) {
var p;
if (requestType === 'rest') {
console.log('makePenpalRequest');
console.log(child);
console.log(child.restRequest);
p = child.restRequest(request);
} else if (requestType === 'fetch') {
p = child.fetchRequest(request);
} else {
p = Promise.resolve({
success: false,
data: 'LWC_API: Invalid request type: ' + requestType
});
}
console.log('makePenpalRequest');
return p.then(function (response) {
console.log(response);
if (response.success) {
return response.data;
}
throw new Error(response.data);
});
}
disconnectedCallback() { // unrender
// this.superUnrender();
// When component unrenders then cleanup penpal
// resources by destroying the connection and nulling out
// the helper's cached reference to the connection and child.
// This ensures that the helper.handleXyzRequest(..) methods
// wait appropriately for the new parent-child handshake to complete
// when this component is re-initialized and scripts are loaded.
if (this._penpal && this._penpal.connection) {
this._penpal.connection.destroy();
this._penpal = {};
}
}
}
TypeError Errors when using Penpal in Lightning Web Component to call Visualforce page via iframe
The catch
is getting an error:
TypeError
With no details.
Reviewing the api.js
component, I think the issue is in method makePenpalRequest
around line:
p = child.restRequest(request);
Because when I do console.log(childconnection.restRequest)
I get undefined
, but child
is a Promisepromise
as expecteddoes not resolve.
/* eslint-disable @lwc/lwc/no-async-operation */
import { LightningElement, wire, api } from 'lwc';
import { loadScript } from 'lightning/platformResourceLoader';
import PP from '@salesforce/resourceUrl/penpal'
import getVisualforceDomainURL from '@salesforce/apex/LC_VisualforceDomainController.getVisualforceDomainURL';
export default class Api extends LightningElement {
_penpal = {};
penpalInitialized = false;
iframeSrc = '';
@wire(getVisualforceDomainURL) wiredDomainUrl({ error, data }) {
if (data) {
this.iframeSrc = data + '/apex/LC_APIPage';
console.log(this.iframeSrc);
this.initializePenpal();
} else if (error) {
console.error('LWC_API: error getting Visualforce Domain URL', error);
this.iframeSrc = undefined;
}
}
connectedCallback() {
Promise.all([
loadScript(this, PP)
]).then(() => { });
}
initializePenpal() {
let initialized = this.penpalInitialized;
var self = this;
// Since the iframe source is calculated asynchronously,
// we listen to the component's render events and each time
// check if the iframe is ready, and if so, then we initialize
// penpal to connect this component to the iframe.
// Since we only want to do this once, we also set the initialized flag.
if (!initialized) {
const container = this.template.querySelector('div');
const iframeElmt = document.createElement('iframe');
iframeElmt.src = this.iframeSrc;
container.appendChild(iframeElmt);
if (iframeElmt != null) {
this.penpalInitialized = true;
// eslint-disable-next-line no-undef
const connection = Penpal.connectToChild({
// The iframe to which a connection should be made
iframe: iframeElmt
});
this._penpal.connection = connection;
Promiseconnection.all([connection])promise.then(function (child) {
// Cache a reference to the child so that we can
// use it in the restRequest/fetchRequest methods,
// as well as be able to destroy it when this component unrenders.
self._penpal.child = child[0];
}).catch(function (err) {
console.error('LWC_API: Error establishing connection to iframe', err);
this.penpalInitialized = false;
});
} // else, iframe source is empty, keep waiting
}
}
// Makes a Salesforce REST API request and returns a promise that resolves to the response.
@api restRequest(request) {
var self = this;
var defaultRequest = {
'method': 'get'
};
var defaultHeaders = {
'Content-Type': 'application/json'
};
request = Object.assign({}, defaultRequest, request);
request.headers = Object.assign({}, defaultHeaders, request.headers);
return this.getPenpalChild().then(function (child) {
return self.makePenpalRequest('rest', child, request);
});
}
@api fetchRequest(request) {
return this.getPenpalChild().then(function (child) {
return this.makePenpalRequest('fetch', child, request);
});
}
// ------------------------------------------------------------
/**
* For internal use.
* Returns a promise waiting for the parent-child postmate handshake to complete
* then resolves with reference to the postmate child for making requests.
*/
getPenpalChild() {
var child;
var self = this;
var timerId;
var timeout = 10000; // ten seconds
var pollFrequency = 500; // half a second
var startTime = new Date().getTime();
var endTime = startTime + timeout;
return new Promise(function (resolve, reject) {
child = self._penpal.child;
if (child) {
resolve(child);
} else {
// all time values in milliseconds
timerId = setInterval(function () {
child = this._penpal.child;
if (child) {
// parent-child postmate handshake now complete
clearInterval(timerId);
resolve(child);
} else {
// check if we have exceeded our timeout
let currentTime = new Date().getTime();
if (currentTime > endTime) {
clearInterval(timerId);
reject('LWC_API: Timeout trying to establish connection to iframe');
}
// else, keep polling
}
}, pollFrequency);
}
});
}
/**
* For internal use.
* Returns a promise waiting for the parent-child postmate request to complete
* then resolves with response from the child iframe.
*/
makePenpalRequest(requestType, child, request) {
var p;
if (requestType === 'rest') {
console.log('makePenpalRequest');
console.log(child);
console.log(child.restRequest);
p = child.restRequest(request);
} else if (requestType === 'fetch') {
p = child.fetchRequest(request);
} else {
p = Promise.resolve({
success: false,
data: 'LWC_API: Invalid request type: ' + requestType
});
}
console.log('makePenpalRequest');
return p.then(function (response) {
console.log(response);
if (response.success) {
return response.data;
}
throw new Error(response.data);
});
}
disconnectedCallback() { // unrender
// this.superUnrender();
// When component unrenders then cleanup penpal
// resources by destroying the connection and nulling out
// the helper's cached reference to the connection and child.
// This ensures that the helper.handleXyzRequest(..) methods
// wait appropriately for the new parent-child handshake to complete
// when this component is re-initialized and scripts are loaded.
if (this._penpal && this._penpal.connection) {
this._penpal.connection.destroy();
this._penpal = {};
}
}
}
TypeError when using Penpal in Lightning Web Component to call Visualforce page via iframe
The catch
is getting an error:
TypeError
With no details.
Reviewing the api.js
component, I think the issue is in method makePenpalRequest
around line:
p = child.restRequest(request);
Because when I do console.log(child.restRequest)
I get undefined
, but child
is a Promise
as expected.
/* eslint-disable @lwc/lwc/no-async-operation */
import { LightningElement, wire, api } from 'lwc';
import { loadScript } from 'lightning/platformResourceLoader';
import PP from '@salesforce/resourceUrl/penpal'
import getVisualforceDomainURL from '@salesforce/apex/LC_VisualforceDomainController.getVisualforceDomainURL';
export default class Api extends LightningElement {
_penpal = {};
penpalInitialized = false;
iframeSrc = '';
@wire(getVisualforceDomainURL) wiredDomainUrl({ error, data }) {
if (data) {
this.iframeSrc = data + '/apex/LC_APIPage';
console.log(this.iframeSrc);
this.initializePenpal();
} else if (error) {
console.error('LWC_API: error getting Visualforce Domain URL', error);
this.iframeSrc = undefined;
}
}
connectedCallback() {
Promise.all([
loadScript(this, PP)
]).then(() => { });
}
initializePenpal() {
let initialized = this.penpalInitialized;
var self = this;
// Since the iframe source is calculated asynchronously,
// we listen to the component's render events and each time
// check if the iframe is ready, and if so, then we initialize
// penpal to connect this component to the iframe.
// Since we only want to do this once, we also set the initialized flag.
if (!initialized) {
const container = this.template.querySelector('div');
const iframeElmt = document.createElement('iframe');
iframeElmt.src = this.iframeSrc;
container.appendChild(iframeElmt);
if (iframeElmt != null) {
this.penpalInitialized = true;
// eslint-disable-next-line no-undef
const connection = Penpal.connectToChild({
// The iframe to which a connection should be made
iframe: iframeElmt
});
this._penpal.connection = connection;
Promise.all([connection]).then(function (child) {
// Cache a reference to the child so that we can
// use it in the restRequest/fetchRequest methods,
// as well as be able to destroy it when this component unrenders.
self._penpal.child = child[0];
}).catch(function (err) {
console.error('LWC_API: Error establishing connection to iframe', err);
this.penpalInitialized = false;
});
} // else, iframe source is empty, keep waiting
}
}
// Makes a Salesforce REST API request and returns a promise that resolves to the response.
@api restRequest(request) {
var self = this;
var defaultRequest = {
'method': 'get'
};
var defaultHeaders = {
'Content-Type': 'application/json'
};
request = Object.assign({}, defaultRequest, request);
request.headers = Object.assign({}, defaultHeaders, request.headers);
return this.getPenpalChild().then(function (child) {
return self.makePenpalRequest('rest', child, request);
});
}
@api fetchRequest(request) {
return this.getPenpalChild().then(function (child) {
return this.makePenpalRequest('fetch', child, request);
});
}
// ------------------------------------------------------------
/**
* For internal use.
* Returns a promise waiting for the parent-child postmate handshake to complete
* then resolves with reference to the postmate child for making requests.
*/
getPenpalChild() {
var child;
var self = this;
var timerId;
var timeout = 10000; // ten seconds
var pollFrequency = 500; // half a second
var startTime = new Date().getTime();
var endTime = startTime + timeout;
return new Promise(function (resolve, reject) {
child = self._penpal.child;
if (child) {
resolve(child);
} else {
// all time values in milliseconds
timerId = setInterval(function () {
child = this._penpal.child;
if (child) {
// parent-child postmate handshake now complete
clearInterval(timerId);
resolve(child);
} else {
// check if we have exceeded our timeout
let currentTime = new Date().getTime();
if (currentTime > endTime) {
clearInterval(timerId);
reject('LWC_API: Timeout trying to establish connection to iframe');
}
// else, keep polling
}
}, pollFrequency);
}
});
}
/**
* For internal use.
* Returns a promise waiting for the parent-child postmate request to complete
* then resolves with response from the child iframe.
*/
makePenpalRequest(requestType, child, request) {
var p;
if (requestType === 'rest') {
console.log('makePenpalRequest');
console.log(child);
console.log(child.restRequest);
p = child.restRequest(request);
} else if (requestType === 'fetch') {
p = child.fetchRequest(request);
} else {
p = Promise.resolve({
success: false,
data: 'LWC_API: Invalid request type: ' + requestType
});
}
console.log('makePenpalRequest');
return p.then(function (response) {
console.log(response);
if (response.success) {
return response.data;
}
throw new Error(response.data);
});
}
disconnectedCallback() { // unrender
// this.superUnrender();
// When component unrenders then cleanup penpal
// resources by destroying the connection and nulling out
// the helper's cached reference to the connection and child.
// This ensures that the helper.handleXyzRequest(..) methods
// wait appropriately for the new parent-child handshake to complete
// when this component is re-initialized and scripts are loaded.
if (this._penpal && this._penpal.connection) {
this._penpal.connection.destroy();
this._penpal = {};
}
}
}
Errors when using Penpal in Lightning Web Component to call Visualforce page via iframe
Reviewing the api.js
component, the connection.promise
does not resolve.
/* eslint-disable @lwc/lwc/no-async-operation */
import { LightningElement, wire, api } from 'lwc';
import { loadScript } from 'lightning/platformResourceLoader';
import PP from '@salesforce/resourceUrl/penpal'
import getVisualforceDomainURL from '@salesforce/apex/LC_VisualforceDomainController.getVisualforceDomainURL';
export default class Api extends LightningElement {
_penpal = {};
penpalInitialized = false;
iframeSrc = '';
@wire(getVisualforceDomainURL) wiredDomainUrl({ error, data }) {
if (data) {
this.iframeSrc = data + '/apex/LC_APIPage';
console.log(this.iframeSrc);
this.initializePenpal();
} else if (error) {
console.error('LWC_API: error getting Visualforce Domain URL', error);
this.iframeSrc = undefined;
}
}
connectedCallback() {
Promise.all([
loadScript(this, PP)
]).then(() => { });
}
initializePenpal() {
let initialized = this.penpalInitialized;
var self = this;
// Since the iframe source is calculated asynchronously,
// we listen to the component's render events and each time
// check if the iframe is ready, and if so, then we initialize
// penpal to connect this component to the iframe.
// Since we only want to do this once, we also set the initialized flag.
if (!initialized) {
const container = this.template.querySelector('div');
const iframeElmt = document.createElement('iframe');
iframeElmt.src = this.iframeSrc;
container.appendChild(iframeElmt);
if (iframeElmt != null) {
this.penpalInitialized = true;
// eslint-disable-next-line no-undef
const connection = Penpal.connectToChild({
// The iframe to which a connection should be made
iframe: iframeElmt
});
this._penpal.connection = connection;
connection.promise.then(function (child) {
// Cache a reference to the child so that we can
// use it in the restRequest/fetchRequest methods,
// as well as be able to destroy it when this component unrenders.
self._penpal.child = child[0];
}).catch(function (err) {
console.error('LWC_API: Error establishing connection to iframe', err);
this.penpalInitialized = false;
});
} // else, iframe source is empty, keep waiting
}
}
// Makes a Salesforce REST API request and returns a promise that resolves to the response.
@api restRequest(request) {
var self = this;
var defaultRequest = {
'method': 'get'
};
var defaultHeaders = {
'Content-Type': 'application/json'
};
request = Object.assign({}, defaultRequest, request);
request.headers = Object.assign({}, defaultHeaders, request.headers);
return this.getPenpalChild().then(function (child) {
return self.makePenpalRequest('rest', child, request);
});
}
@api fetchRequest(request) {
return this.getPenpalChild().then(function (child) {
return this.makePenpalRequest('fetch', child, request);
});
}
// ------------------------------------------------------------
/**
* For internal use.
* Returns a promise waiting for the parent-child postmate handshake to complete
* then resolves with reference to the postmate child for making requests.
*/
getPenpalChild() {
var child;
var self = this;
var timerId;
var timeout = 10000; // ten seconds
var pollFrequency = 500; // half a second
var startTime = new Date().getTime();
var endTime = startTime + timeout;
return new Promise(function (resolve, reject) {
child = self._penpal.child;
if (child) {
resolve(child);
} else {
// all time values in milliseconds
timerId = setInterval(function () {
child = this._penpal.child;
if (child) {
// parent-child postmate handshake now complete
clearInterval(timerId);
resolve(child);
} else {
// check if we have exceeded our timeout
let currentTime = new Date().getTime();
if (currentTime > endTime) {
clearInterval(timerId);
reject('LWC_API: Timeout trying to establish connection to iframe');
}
// else, keep polling
}
}, pollFrequency);
}
});
}
/**
* For internal use.
* Returns a promise waiting for the parent-child postmate request to complete
* then resolves with response from the child iframe.
*/
makePenpalRequest(requestType, child, request) {
var p;
if (requestType === 'rest') {
console.log('makePenpalRequest');
console.log(child);
console.log(child.restRequest);
p = child.restRequest(request);
} else if (requestType === 'fetch') {
p = child.fetchRequest(request);
} else {
p = Promise.resolve({
success: false,
data: 'LWC_API: Invalid request type: ' + requestType
});
}
console.log('makePenpalRequest');
return p.then(function (response) {
console.log(response);
if (response.success) {
return response.data;
}
throw new Error(response.data);
});
}
disconnectedCallback() { // unrender
// this.superUnrender();
// When component unrenders then cleanup penpal
// resources by destroying the connection and nulling out
// the helper's cached reference to the connection and child.
// This ensures that the helper.handleXyzRequest(..) methods
// wait appropriately for the new parent-child handshake to complete
// when this component is re-initialized and scripts are loaded.
if (this._penpal && this._penpal.connection) {
this._penpal.connection.destroy();
this._penpal = {};
}
}
}
Reviewing the api.js
component, I thinikthink the issue is in method makePenpalRequest
around line:
Reviewing the api.js
component, I thinik the issue is in method makePenpalRequest
around line:
Reviewing the api.js
component, I think the issue is in method makePenpalRequest
around line: