NodeJS Cannot read property 'length' of undefined - MagicMirror Module - javascript

I'm working on a prototype of a MagicMirror Module that pulls data in from this json feed https://jsonplaceholder.typicode.com/todos/1. It passes fine on json parse payload But fails somewhere in within tArray length with cannot ready property 'length' of undefined. I'm suspecting the JSON isn't being carried to tArray properly, but i'm a at a loss. Below are my two files!
node_helper.js
'use strict';
/* Magic Mirror
* Module:
*/
const NodeHelper = require('node_helper');
var request = require('request');
var moment = require('moment');
module.exports = NodeHelper.create({
start: function() {
this.started = false;
this.config = null;
},
getData: function() {
var self = this;
var myUrl = "https://jsonplaceholder.typicode.com/todos/1";
request({
url: myUrl,
method: 'GET',
headers: { 'API_TOKEN': this.config.apiKey }
}, function (error, response, body) {
console.log(body);
if (!error && response.statusCode == 200) {
self.sendSocketNotification("DATA", body);
}
});
setTimeout(function() { self.getData(); }, this.config.refreshInterval);
},
socketNotificationReceived: function(notification, payload) {
var self = this;
if (notification === 'CONFIG' && self.started == false) {
self.config = payload;
self.sendSocketNotification("STARTED", true);
self.getData();
self.started = true;
}
}
});
MMM-Fi.js
/* Magic Mirror
*/
Module.register('MMM-Fi',{
defaults: {
animationSpeed: 1000,
refreshInterval: 1000 * 60, //refresh every minute
updateInterval: 1000 * 3600, //update every hour
lang: config.language,
initialLoadDelay: 0, // 0 seconds delay
retryDelay: 5,
},
// Define required scripts.
getScripts: function() {
return ["moment.js", "font-awesome.css"];
},
getStyles: function() {
return ['MMM-Fi.css'];
},
start: function() {
Log.info('Starting module: ' + this.name);
this.loaded = false;
this.sendSocketNotification('CONFIG', this.config);
},
getDom: function() {
var wrapper = document.createElement("div");
if (this.config.apiKey === "") {
wrapper.innerHTML = "No Fi <i>apiKey</i> set in config file.";
wrapper.className = "dimmed light small";
return wrapper;
}
if (this.config.googleApiKey === "") {
wrapper.innerHTML = "No Google <i>api Key</i> set in config file.";
wrapper.className = "dimmed light small";
return wrapper;
}
if (!this.loaded) {
wrapper.innerHTML = this.translate('LOADING');
wrapper.className = "dimmed light small";
return wrapper;
}
if (!this.tArray.length) {
wrapper.innerHTML = "No data";
wrapper.className = "dimmed light small";
return wrapper;
}
var table = document.createElement("table");
table.id = "fitable";
table.className = "small thin light";
var row = document.createElement("tr");
var lineHeader = document.createElement("th");
lineHeader.innerHTML = "test2";
lineHeader.colSpan = 2;
row.appendChild(lineHeader);
table.appendChild(row);
for (var i in this.tArray) {
var currentDeparture = this.tArray[i];
console.log(currentDeparture.title)
}
wrapper.appendChild(table);
return wrapper;
},
tFi: function(data) {
if (!data.listT) {
return;
}
this.tArray = [];
for (var i in data.listT) {
var t = data.listT[i];
this.tArray.push({
userId: t.userId,
id: t.id,
title: t.title,
completed: t.completed,
});
}
return;
},
socketNotificationReceived: function(notification, payload) {
if (notification === "STARTED") {
this.updateDom();
}
else if (notification === "DATA") {
this.loaded = true;
this.tFi(JSON.parse(payload));
this.updateDom();
}
}
});

Related

Append HTML tags using Cloudflare Workers

I'm using a Cloudflare Worker to load data from Backblaze B2. It generates a basic HTML page like this:
<html>
<head><meta name="viewport" content="width=device-width"></head>
<body>
<video>
<source src="myvideo.mp4" type="video/mp4">
</video>
</body>
</html>
I'm trying to modify the script so the browser will load a AV1-encoded version, if supported. If it is not then fallback to the WebM/VP9 version.
The HTML would look like the code below, but I cannot figure out how to modify the script correctly:
<html>
<head><meta name="viewport" content="width=device-width"></head>
<body>
<video>
<source src="myvideo.mp4" type="video/mp4">
<source src="myvideo.webm" type="video/webm">
</video>
</body>
</html>
The Worker code I'm using is:
"use strict";
(() => {
// node_modules/aws4fetch/dist/aws4fetch.esm.mjs
var encoder = new TextEncoder();
var HOST_SERVICES = {
appstream2: "appstream",
cloudhsmv2: "cloudhsm",
email: "ses",
marketplace: "aws-marketplace",
mobile: "AWSMobileHubService",
pinpoint: "mobiletargeting",
queue: "sqs",
"git-codecommit": "codecommit",
"mturk-requester-sandbox": "mturk-requester",
"personalize-runtime": "personalize"
};
var UNSIGNABLE_HEADERS = /* #__PURE__ */ new Set([
"authorization",
"content-type",
"content-length",
"user-agent",
"presigned-expires",
"expect",
"x-amzn-trace-id",
"range",
"connection"
]);
var AwsClient = class {
constructor({ accessKeyId, secretAccessKey, sessionToken, service, region, cache, retries, initRetryMs }) {
if (accessKeyId == null)
throw new TypeError("accessKeyId is a required option");
if (secretAccessKey == null)
throw new TypeError("secretAccessKey is a required option");
this.accessKeyId = accessKeyId;
this.secretAccessKey = secretAccessKey;
this.sessionToken = sessionToken;
this.service = service;
this.region = region;
this.cache = cache || /* #__PURE__ */ new Map();
this.retries = retries != null ? retries : 10;
this.initRetryMs = initRetryMs || 50;
}
async sign(input, init) {
if (input instanceof Request) {
const { method, url, headers, body } = input;
init = Object.assign({ method, url, headers }, init);
if (init.body == null && headers.has("Content-Type")) {
init.body = body != null && headers.has("X-Amz-Content-Sha256") ? body : await input.clone().arrayBuffer();
}
input = url;
}
const signer = new AwsV4Signer(Object.assign({ url: input }, init, this, init && init.aws));
const signed = Object.assign({}, init, await signer.sign());
delete signed.aws;
try {
return new Request(signed.url.toString(), signed);
} catch (e) {
if (e instanceof TypeError) {
return new Request(signed.url.toString(), Object.assign({ duplex: "half" }, signed));
}
throw e;
}
}
async fetch(input, init) {
for (let i = 0; i <= this.retries; i++) {
const fetched = fetch(await this.sign(input, init));
if (i === this.retries) {
return fetched;
}
const res = await fetched;
if (res.status < 500 && res.status !== 429) {
return res;
}
await new Promise((resolve) => setTimeout(resolve, Math.random() * this.initRetryMs * Math.pow(2, i)));
}
throw new Error("An unknown error occurred, ensure retries is not negative");
}
};
var AwsV4Signer = class {
constructor({ method, url, headers, body, accessKeyId, secretAccessKey, sessionToken, service, region, cache, datetime, signQuery, appendSessionToken, allHeaders, singleEncode }) {
if (url == null)
throw new TypeError("url is a required option");
if (accessKeyId == null)
throw new TypeError("accessKeyId is a required option");
if (secretAccessKey == null)
throw new TypeError("secretAccessKey is a required option");
this.method = method || (body ? "POST" : "GET");
this.url = new URL(url);
this.headers = new Headers(headers || {});
this.body = body;
this.accessKeyId = accessKeyId;
this.secretAccessKey = secretAccessKey;
this.sessionToken = sessionToken;
let guessedService, guessedRegion;
if (!service || !region) {
[guessedService, guessedRegion] = guessServiceRegion(this.url, this.headers);
}
this.service = service || guessedService || "";
this.region = region || guessedRegion || "us-east-1";
this.cache = cache || /* #__PURE__ */ new Map();
this.datetime = datetime || new Date().toISOString().replace(/[:-]|\.\d{3}/g, "");
this.signQuery = signQuery;
this.appendSessionToken = appendSessionToken || this.service === "iotdevicegateway";
this.headers.delete("Host");
if (this.service === "s3" && !this.signQuery && !this.headers.has("X-Amz-Content-Sha256")) {
this.headers.set("X-Amz-Content-Sha256", "UNSIGNED-PAYLOAD");
}
const params = this.signQuery ? this.url.searchParams : this.headers;
params.set("X-Amz-Date", this.datetime);
if (this.sessionToken && !this.appendSessionToken) {
params.set("X-Amz-Security-Token", this.sessionToken);
}
this.signableHeaders = ["host", ...this.headers.keys()].filter((header) => allHeaders || !UNSIGNABLE_HEADERS.has(header)).sort();
this.signedHeaders = this.signableHeaders.join(";");
this.canonicalHeaders = this.signableHeaders.map((header) => header + ":" + (header === "host" ? this.url.host : (this.headers.get(header) || "").replace(/\s+/g, " "))).join("\n");
this.credentialString = [this.datetime.slice(0, 8), this.region, this.service, "aws4_request"].join("/");
if (this.signQuery) {
if (this.service === "s3" && !params.has("X-Amz-Expires")) {
params.set("X-Amz-Expires", "86400");
}
params.set("X-Amz-Algorithm", "AWS4-HMAC-SHA256");
params.set("X-Amz-Credential", this.accessKeyId + "/" + this.credentialString);
params.set("X-Amz-SignedHeaders", this.signedHeaders);
}
if (this.service === "s3") {
try {
this.encodedPath = decodeURIComponent(this.url.pathname.replace(/\+/g, " "));
} catch (e) {
this.encodedPath = this.url.pathname;
}
} else {
this.encodedPath = this.url.pathname.replace(/\/+/g, "/");
}
if (!singleEncode) {
this.encodedPath = encodeURIComponent(this.encodedPath).replace(/%2F/g, "/");
}
this.encodedPath = encodeRfc3986(this.encodedPath);
const seenKeys = /* #__PURE__ */ new Set();
this.encodedSearch = [...this.url.searchParams].filter(([k]) => {
if (!k)
return false;
if (this.service === "s3") {
if (seenKeys.has(k))
return false;
seenKeys.add(k);
}
return true;
}).map((pair) => pair.map((p) => encodeRfc3986(encodeURIComponent(p)))).sort(([k1, v1], [k2, v2]) => k1 < k2 ? -1 : k1 > k2 ? 1 : v1 < v2 ? -1 : v1 > v2 ? 1 : 0).map((pair) => pair.join("=")).join("&");
}
async sign() {
if (this.signQuery) {
this.url.searchParams.set("X-Amz-Signature", await this.signature());
if (this.sessionToken && this.appendSessionToken) {
this.url.searchParams.set("X-Amz-Security-Token", this.sessionToken);
}
} else {
this.headers.set("Authorization", await this.authHeader());
}
return {
method: this.method,
url: this.url,
headers: this.headers,
body: this.body
};
}
async authHeader() {
return [
"AWS4-HMAC-SHA256 Credential=" + this.accessKeyId + "/" + this.credentialString,
"SignedHeaders=" + this.signedHeaders,
"Signature=" + await this.signature()
].join(", ");
}
async signature() {
const date = this.datetime.slice(0, 8);
const cacheKey = [this.secretAccessKey, date, this.region, this.service].join();
let kCredentials = this.cache.get(cacheKey);
if (!kCredentials) {
const kDate = await hmac("AWS4" + this.secretAccessKey, date);
const kRegion = await hmac(kDate, this.region);
const kService = await hmac(kRegion, this.service);
kCredentials = await hmac(kService, "aws4_request");
this.cache.set(cacheKey, kCredentials);
}
return buf2hex(await hmac(kCredentials, await this.stringToSign()));
}
async stringToSign() {
return [
"AWS4-HMAC-SHA256",
this.datetime,
this.credentialString,
buf2hex(await hash(await this.canonicalString()))
].join("\n");
}
async canonicalString() {
return [
this.method.toUpperCase(),
this.encodedPath,
this.encodedSearch,
this.canonicalHeaders + "\n",
this.signedHeaders,
await this.hexBodyHash()
].join("\n");
}
async hexBodyHash() {
let hashHeader = this.headers.get("X-Amz-Content-Sha256") || (this.service === "s3" && this.signQuery ? "UNSIGNED-PAYLOAD" : null);
if (hashHeader == null) {
if (this.body && typeof this.body !== "string" && !("byteLength" in this.body)) {
throw new Error("body must be a string, ArrayBuffer or ArrayBufferView, unless you include the X-Amz-Content-Sha256 header");
}
hashHeader = buf2hex(await hash(this.body || ""));
}
return hashHeader;
}
};
async function hmac(key, string) {
const cryptoKey = await crypto.subtle.importKey(
"raw",
typeof key === "string" ? encoder.encode(key) : key,
{ name: "HMAC", hash: { name: "SHA-256" } },
false,
["sign"]
);
return crypto.subtle.sign("HMAC", cryptoKey, encoder.encode(string));
}
async function hash(content) {
return crypto.subtle.digest("SHA-256", typeof content === "string" ? encoder.encode(content) : content);
}
function buf2hex(buffer) {
return Array.prototype.map.call(new Uint8Array(buffer), (x) => ("0" + x.toString(16)).slice(-2)).join("");
}
function encodeRfc3986(urlEncodedStr) {
return urlEncodedStr.replace(/[!'()*]/g, (c) => "%" + c.charCodeAt(0).toString(16).toUpperCase());
}
function guessServiceRegion(url, headers) {
const { hostname, pathname } = url;
if (hostname.endsWith(".r2.cloudflarestorage.com")) {
return ["s3", "auto"];
}
if (hostname.endsWith(".backblazeb2.com")) {
const match2 = hostname.match(/^(?:[^.]+\.)?s3\.([^.]+)\.backblazeb2\.com$/);
return match2 != null ? ["s3", match2[1]] : ["", ""];
}
const match = hostname.replace("dualstack.", "").match(/([^.]+)\.(?:([^.]*)\.)?amazonaws\.com(?:\.cn)?$/);
let [service, region] = (match || ["", ""]).slice(1, 3);
if (region === "us-gov") {
region = "us-gov-west-1";
} else if (region === "s3" || region === "s3-accelerate") {
region = "us-east-1";
service = "s3";
} else if (service === "iot") {
if (hostname.startsWith("iot.")) {
service = "execute-api";
} else if (hostname.startsWith("data.jobs.iot.")) {
service = "iot-jobs-data";
} else {
service = pathname === "/mqtt" ? "iotdevicegateway" : "iotdata";
}
} else if (service === "autoscaling") {
const targetPrefix = (headers.get("X-Amz-Target") || "").split(".")[0];
if (targetPrefix === "AnyScaleFrontendService") {
service = "application-autoscaling";
} else if (targetPrefix === "AnyScaleScalingPlannerFrontendService") {
service = "autoscaling-plans";
}
} else if (region == null && service.startsWith("s3-")) {
region = service.slice(3).replace(/^fips-|^external-1/, "");
service = "s3";
} else if (service.endsWith("-fips")) {
service = service.slice(0, -5);
} else if (region && /-\d$/.test(service) && !/-\d$/.test(region)) {
[service, region] = [region, service];
}
return [HOST_SERVICES[service] || service, region];
}
// index.js
var UNSIGNABLE_HEADERS2 = [
"x-forwarded-proto",
"x-real-ip"
];
function filterHeaders(headers) {
return Array.from(headers.entries()).filter((pair) => !UNSIGNABLE_HEADERS2.includes(pair[0]) && !pair[0].startsWith("cf-"));
}
async function handleRequest(event, client2) {
const request = event.request;
if (!["GET", "HEAD"].includes(request.method)) {
return new Response(null, {
status: 405,
statusText: "Method Not Allowed"
});
}
const url = new URL(request.url);
let path = url.pathname.replace(/^\//, "");
path = path.replace(/\/$/, "");
const pathSegments = path.split("/");
if (ALLOW_LIST_BUCKET !== "true") {
if (BUCKET_NAME === "$path" && pathSegments[0].length < 2 || BUCKET_NAME !== "$path" && path.length === 0) {
return new Response(null, {
status: 404,
statusText: "Not Found"
});
}
}
switch (BUCKET_NAME) {
case "$path":
url.hostname = B2_ENDPOINT;
break;
break;
case "$host":
url.hostname = url.hostname.split(".")[0] + "." + B2_ENDPOINT;
break;
default:
url.hostname = BUCKET_NAME + "." + B2_ENDPOINT;
break;
}
const headers = filterHeaders(request.headers);
const signedRequest = await client2.sign(url.toString(), {
method: request.method,
headers,
body: request.body
});
return fetch(signedRequest);
}
var endpointRegex = /^s3\.([a-zA-Z0-9-]+)\.backblazeb2\.com$/;
var [, aws_region] = B2_ENDPOINT.match(endpointRegex);
var client = new AwsClient({
"accessKeyId": B2_APPLICATION_KEY_ID,
"secretAccessKey": B2_APPLICATION_KEY,
"service": "s3",
"region": aws_region
});
addEventListener("fetch", function(event) {
event.respondWith(handleRequest(event, client));
});
})();
/**
* #license MIT <https://opensource.org/licenses/MIT>
* #copyright Michael Hart 2022
*/
//# sourceMappingURL=index.js.map
[1]: https://github.com/backblaze-b2-samples/cloudflare-b2

How to properly extend the Promise class?

I have a custom Promise2 class that extends Promise class to allow early settling. It uses my custom Timer class to check the progress of a simulated activity through another timer t1. In my example, p1 does an early settling but the problem is with the p1.then( doesn't recognize the onfulfilled callback as a function.
I suspected I have to override then() and call the super.then() but it didn't work. By the way, the timed executor callback inside super() is just a workaround to make this accessible. Any ideas on what's lacking in my Promise2 class?
JavaScript Code
'use strict';
const p1 = new Promise2(
(resolve, reject) => {
const t1 = Timer.create(
() => {
resolve('Promise resolved.');
// reject(new Error('Promise rejected.'));
},
3000,
);
return { timer: t1 };
},
);
Timer.create(
() => {
const { isCompleted } = p1.return.timer;
const { progress } = p1.return.timer;
if (isCompleted === false) {
console.log(`Promise: ${progress} %`);
if (progress > 50) {
p1.resolve('Early resolve.');
// p1.reject(new Error('Early reject.'));
p1.return.timer.stop();
}
}
},
250,
true,
16,
);
// p1.promise.then(
p1.then(
(value) => {
console.log('__resolve__');
console.log(value);
},
)
.catch(
(reason) => {
console.log('__catch__');
console.log(reason);
},
);
Promise2 Class
class Promise2 extends Promise {
constructor(executor = null) {
super(
(resolve, reject) => {
Timer.create(
() => {
this.resolve = resolve;
this.reject = reject;
this.return = executor(resolve, reject);
},
1);
},
);
// this.promise = new Promise(
// (resolve, reject) => {
// this.resolve = resolve;
// this.reject = reject;
// this.return = executor(resolve, reject);
// },
// );
}
static create(executor = null) {
return new Promise2(...arguments);
}
}
Timer Class
class Timer {
constructor(workload = null, milliseconds = 1000, isAutostart = true, repeat = 1, isInterval = false) {
this.workload = workload;
this.milliseconds = milliseconds;
this.isAutostart = isAutostart;
this.repeat = repeat;
this.isInterval = isInterval;
this.startTime = 0;
this.endTime = 0;
this.timeLeft = milliseconds;
this.timeoutId = 0;
this.progress = 0;
this.isCompleted = false;
this.endTimeActual = 0;
this.repeatLeft = repeat;
this.isPaused = false;
this.subTimers = [];
if (isAutostart === true) {
this.start();
}
}
start(thisArg = this) {
thisArg.startTime = Date.now();
thisArg.endTime = thisArg.startTime + thisArg.milliseconds;
const timeoutEndTime = Date.now();
thisArg.watch(thisArg.workload, timeoutEndTime, thisArg);
}
watch(workload = null, timeoutEndTime = 0, thisArg = this) {
if (thisArg.isPaused === true) {
return;
}
const timeoutLag = Date.now() - timeoutEndTime;
thisArg.timeLeft = thisArg.endTime - Date.now() - timeoutLag;
if (thisArg.timeLeft > 0) {
thisArg.progress = 100 - ((thisArg.timeLeft / thisArg.milliseconds) * 100);
const inProgress = 100 - thisArg.progress;
const tick = thisArg.timeLeft / inProgress;
timeoutEndTime = Date.now() + tick;
thisArg.timeoutId = setTimeout(thisArg.watch, tick, thisArg.workload, timeoutEndTime, thisArg);
return;
}
thisArg.stop(thisArg);
workload();
if (thisArg.repeatLeft > 0) {
thisArg.isCompleted = false;
thisArg.start();
}
if (thisArg.isInterval === true) {
thisArg.repeatLeft = 1;
}
if (thisArg.subTimers.length > 0) {
thisArg.subTimers.forEach(
(timer) => {
if (timer.isAutostart === true) {
timer.start();
}
},
);
}
}
stop(thisArg = this) {
clearTimeout(thisArg.timeoutId);
thisArg.isCompleted = true;
thisArg.endTimeActual = Date.now();
thisArg.repeatLeft -= 1;
if (thisArg.isInterval === true) {
thisArg.repeatLeft = 0;
}
}
restart(thisArg = this) {
thisArg.stop();
thisArg.startTime = 0;
thisArg.endTime = 0;
thisArg.timeLeft = thisArg.milliseconds;
thisArg.timeoutId = 0;
thisArg.progress = 0;
thisArg.isCompleted = false;
thisArg.endTimeActual = 0;
thisArg.repeatLeft = thisArg.repeat;
thisArg.start();
}
pause(thisArg = this) {
thisArg.isPaused = true;
}
resume(thisArg = this) {
thisArg.isPaused = false;
const timeoutEndTime = Date.now();
thisArg.watch(thisArg.workload, timeoutEndTime, thisArg);
}
static create(workload = null, milliseconds = 1000, isAutostart = true, repeat = 1, isInterval = false) {
return new Timer(...arguments);
}
static chain(timers = []) {
const timerReferences = Timer.chainWalk(timers);
if (timerReferences[0].isAutostart === true) {
timerReferences[0].start();
}
return timerReferences;
}
static chainWalk(timers = [], timerReferences = [], nextTimer = null) {
if (timers.length === 0) {
return timerReferences;
}
if (timerReferences.length === 0) {
timers = [...timers];
}
const timer = timers.shift();
const {
workload = null,
milliseconds = 1000,
isAutostart = true,
repeat = 1,
isInterval = false,
} = timer;
const newTimer = new Timer(workload, milliseconds, false, repeat, isInterval);
newTimer.isAutostart = isAutostart;
if (timerReferences.length === 0) {
timerReferences.push(newTimer);
[nextTimer] = timerReferences;
} else {
nextTimer.subTimers.push(newTimer);
[nextTimer] = nextTimer.subTimers;
}
timerReferences = Timer.chainWalk(timers, timerReferences, nextTimer);
return timerReferences;
}
static tree(timers = []) {
const timerReferences = Timer.treeWalk(timers);
timerReferences.forEach(
(reference) => {
if (reference.isAutostart === true) {
reference.start();
}
},
);
return timerReferences;
}
static treeWalk(timers = []) {
const timerReferences = [];
timers.forEach(
(timer) => {
const {
workload = null,
milliseconds = 1000,
isAutostart = true,
repeat = 1,
isInterval = false,
subTimers = [],
} = timer;
const newTimer = new Timer(workload, milliseconds, false, repeat, isInterval);
newTimer.isAutostart = isAutostart;
if (Array.isArray(subTimers) === true) {
newTimer.subTimers = Timer.treeWalk(subTimers);
}
timerReferences.push(newTimer);
},
);
return timerReferences;
}
}
Console Output
Promise2 Class (Working Alternative)
class Promise2 {
constructor(executor = null) {
this.promise = new Promise(
(resolve, reject) => {
this.resolve = resolve;
this.reject = reject;
this.return = executor(resolve, reject);
},
);
this.then = function (onfulfilled = null, onrejected = null) {
return this.promise.then(...arguments);
};
this.catch = function (onrejected = null) {
return this.promise.catch(...arguments);
};
this.finally = function (onfinally = null) {
return this.promise.finally(...arguments);
};
}
static create(executor = null) {
return new Promise2(...arguments);
}
}

JavaScript Promise return value from function

Relatively new to JavaScript Promises.
Trying to call a function - checktheData(recordidGuid) from within a Promise
and use the result in a .then chain.
The last line of the checktheData function is:
return outcomeString
My problem is that the result of the promise is "undefined", yet when I output it to the console in the checktheData function it is as expected
I know I need to add a return statement, but where please?
Simple code:
function masterDeploy(PrimaryControl){
var formContext = PrimaryControl;
formContext.data.refresh(true);
var recordidGuid = ""
recordidGuid = formContext.data.entity.getId();
var loggedinuser =
Xrm.Utility.getGlobalContext().userSettings.userId;
recordidGuid = recordidGuid.replace('{', '').replace('}', '');
loggedinuser = loggedinuser.replace('{', '').replace('}', '');
var outcomeString = ""
var checkOutcome = false;
let promise = new Promise(function(resolve, reject) {
resolve(checktheData(recordidGuid))
});
promise.then(
result => {
console.log(promise);
}
),
promise.catch(
function (error){
DisplayError(error)}
);
return // stops here whilst debugging
if (checkOutcome == true){
var alertStrings = { confirmButtonLabel: "Close", text: outcomeString, title: "Data check failed" };
var alertOptions = { height: 500, width: 1000 };
Xrm.Navigation.openAlertDialog(alertStrings, alertOptions).then(
function success(result) {
return;
},
function (error) {
DisplayError(error)
});
}
else{
if(checkOutcome == false){
//2. Create the learner journal url
buildLearnerEntryURL(recordidGuid,loggedinuser)
if(checkOutcome == false){
//3. Create refinery user and enrol on courses
createUserandEnrol(recordidGuid,loggedinuser)
if(checkOutcome == false){
//4. Create Learning Aims
createLearningAims(recordidGuid)
}
};
};
}
formContext.data.refresh(true);
//Set text to be a concatenated summary of actions completed or skipped
alertStrings = { confirmButtonLabel: "Close", text: "Deployment completed etc etc", title: "Deployment Completed" };
Xrm.Navigation.openAlertDialog(alertStrings, alertOptions).then(
function success(result) {
return;
},
function (error) {
DisplayError(error)
});
};
function checktheData(recordidGuid){
var outcomeString = ""
var checkOutcome = "false";
var str = "";
Xrm.WebApi.online.retrieveRecord("new_apprenticeshipflight", recordidGuid, "?$select=new_flighttype,new_programmelearningaimreference,new_apprenticeshipoverallaimreference,_new_mentor_value,_new_enrolledstandard_value,_new_clonelinkid_value,new_plannedstartdate,new_plannedenddate,crd80_overideendcalc,_new_contact_value,_new_apprenticeshipprogramme_value,_new_employer_value,_crd80_locationcontact_value,crd80_headofficedelivery,crd80_learningjournalurl,crd80_refineryid,crd80_addresstouse,_crd80_placementemployer_value,crd80_employeraddresstext,&$expand=new_Contact($select=emailaddress1,firstname,lastname),new_EnrolledStandard($select=crd80_learningjournalform),crd80_PlacementEmployer($select=name, accountid, address1_postalcode,address2_postalcode),crd80_LocationContact($select=emailaddress1,fullname,telephone1),new_Employer($select=name,address1_postalcode,address2_postalcode),new_Mentor($select=new_homepostcode),new_ApprenticeshipProgramme($select=crd80_learnerteamsiteurl)").then(
function success(result) {
if (result["new_flighttype"] == 100000001 && result["new_flighttype"] == null){outcomeString = outcomeString + "This must be a learner type flight"; checkOutcome = true};
//other lines removed for clarity
console.log(outcomeString)
return outcomeString
})
}
Xrm.WebApi.online.retrieveRecord return a promise, so you can just return it from checktheData().
What you need to handle is basically just to call the checktheData() and use .then() and .catch() for the result.
Example:
function masterDeploy(PrimaryControl) {
var formContext = PrimaryControl;
formContext.data.refresh(true);
var recordidGuid = "";
recordidGuid = formContext.data.entity.getId();
var loggedinuser = Xrm.Utility.getGlobalContext().userSettings.userId;
recordidGuid = recordidGuid.replace("{", "").replace("}", "");
loggedinuser = loggedinuser.replace("{", "").replace("}", "");
var outcomeString = "";
checktheData()
.then(checkOutcome => {
if (checkOutcome == true) {
var alertStrings = {
confirmButtonLabel: "Close",
text: outcomeString,
title: "Data check failed",
};
var alertOptions = { height: 500, width: 1000 };
Xrm.Navigation.openAlertDialog(alertStrings, alertOptions).then(
function success(result) {
return;
},
function (error) {
DisplayError(error);
}
);
} else {
if (checkOutcome == false) {
//2. Create the learner journal url
buildLearnerEntryURL(recordidGuid, loggedinuser);
if (checkOutcome == false) {
//3. Create refinery user and enrol on courses
createUserandEnrol(recordidGuid, loggedinuser);
if (checkOutcome == false) {
//4. Create Learning Aims
createLearningAims(recordidGuid);
}
}
}
}
formContext.data.refresh(true);
//Set text to be a concatenated summary of actions completed or skipped
alertStrings = {
confirmButtonLabel: "Close",
text: "Deployment completed etc etc",
title: "Deployment Completed",
};
Xrm.Navigation.openAlertDialog(alertStrings, alertOptions)
.then(function success(result) {
return;
})
.catch(error => {
DisplayError(error);
});
})
.catch(err => {
console.log(err);
});
}
function checktheData(recordidGuid) {
var outcomeString = "";
var checkOutcome = "false";
var str = "";
Xrm.WebApi.online
.retrieveRecord(
"new_apprenticeshipflight",
recordidGuid,
"?$select=new_flighttype,new_programmelearningaimreference,new_apprenticeshipoverallaimreference,_new_mentor_value,_new_enrolledstandard_value,_new_clonelinkid_value,new_plannedstartdate,new_plannedenddate,crd80_overideendcalc,_new_contact_value,_new_apprenticeshipprogramme_value,_new_employer_value,_crd80_locationcontact_value,crd80_headofficedelivery,crd80_learningjournalurl,crd80_refineryid,crd80_addresstouse,_crd80_placementemployer_value,crd80_employeraddresstext,&$expand=new_Contact($select=emailaddress1,firstname,lastname),new_EnrolledStandard($select=crd80_learningjournalform),crd80_PlacementEmployer($select=name, accountid, address1_postalcode,address2_postalcode),crd80_LocationContact($select=emailaddress1,fullname,telephone1),new_Employer($select=name,address1_postalcode,address2_postalcode),new_Mentor($select=new_homepostcode),new_ApprenticeshipProgramme($select=crd80_learnerteamsiteurl)"
)
.then(function success(result) {
if (
result["new_flighttype"] == 100000001 &&
result["new_flighttype"] == null
) {
outcomeString = outcomeString + "This must be a learner type flight";
checkOutcome = true;
}
//other lines removed for clarity
console.log(outcomeString);
return outcomeString;
});
}
Another example with async/await approach.
async function masterDeploy(PrimaryControl) {
var formContext = PrimaryControl;
formContext.data.refresh(true);
var recordidGuid = "";
recordidGuid = formContext.data.entity.getId();
var loggedinuser = Xrm.Utility.getGlobalContext().userSettings.userId;
recordidGuid = recordidGuid.replace("{", "").replace("}", "");
loggedinuser = loggedinuser.replace("{", "").replace("}", "");
var outcomeString = "";
const checkOutcome = await checktheData();
if (checkOutcome == true) {
var alertStrings = {
confirmButtonLabel: "Close",
text: outcomeString,
title: "Data check failed",
};
var alertOptions = { height: 500, width: 1000 };
try {
const result = await Xrm.Navigation.openAlertDialog(
alertStrings,
alertOptions
);
} catch (err) {
DisplayError(err);
}
} else {
if (checkOutcome == false) {
//2. Create the learner journal url
buildLearnerEntryURL(recordidGuid, loggedinuser);
if (checkOutcome == false) {
//3. Create refinery user and enrol on courses
createUserandEnrol(recordidGuid, loggedinuser);
if (checkOutcome == false) {
//4. Create Learning Aims
createLearningAims(recordidGuid);
}
}
}
}
formContext.data.refresh(true);
//Set text to be a concatenated summary of actions completed or skipped
alertStrings = {
confirmButtonLabel: "Close",
text: "Deployment completed etc etc",
title: "Deployment Completed",
};
try {
const result = await Xrm.Navigation.openAlertDialog(
alertStrings,
alertOptions
);
} catch (err) {
DisplayError(err);
}
}
async function checktheData(recordidGuid) {
var outcomeString = "";
var checkOutcome = "false";
var str = "";
const result = await Xrm.WebApi.online.retrieveRecord(
"new_apprenticeshipflight",
recordidGuid,
"?$select=new_flighttype,new_programmelearningaimreference,new_apprenticeshipoverallaimreference,_new_mentor_value,_new_enrolledstandard_value,_new_clonelinkid_value,new_plannedstartdate,new_plannedenddate,crd80_overideendcalc,_new_contact_value,_new_apprenticeshipprogramme_value,_new_employer_value,_crd80_locationcontact_value,crd80_headofficedelivery,crd80_learningjournalurl,crd80_refineryid,crd80_addresstouse,_crd80_placementemployer_value,crd80_employeraddresstext,&$expand=new_Contact($select=emailaddress1,firstname,lastname),new_EnrolledStandard($select=crd80_learningjournalform),crd80_PlacementEmployer($select=name, accountid, address1_postalcode,address2_postalcode),crd80_LocationContact($select=emailaddress1,fullname,telephone1),new_Employer($select=name,address1_postalcode,address2_postalcode),new_Mentor($select=new_homepostcode),new_ApprenticeshipProgramme($select=crd80_learnerteamsiteurl)"
);
if (
result["new_flighttype"] == 100000001 &&
result["new_flighttype"] == null
) {
outcomeString = outcomeString + "This must be a learner type flight";
checkOutcome = true;
}
//other lines removed for clarity
console.log(outcomeString);
return outcomeString;
}

How do i use nativescript load on demand funtion

EDIT
i was able to get it to work, but one problem now is, before it creates and additional empty item before showing other items.
NB the load on demand function works fine, but i don't know why an additional empty item is created. i guess there's an issue with my code
const viewModel = observableModule.fromObject({
_sourceDataItems: [],
dataItems: new ObservableArray(),
initDataItems: function () {
var url="https://adekunletestprojects.000webhostapp.com/skog/searchResults.php?search=" + encodeURIComponent("Adeyeye") + "&location=" + encodeURIComponent("Lagos");
fetch(url).then((response) => response.json()).then((res) => {
this._sourceDataItems = new ObservableArray(res.items);
this.dataItems.push(this._sourceDataItems);
}).catch((err) => {
var toast = Toast.makeText("Unable to load users");
toast.show();
});
},
addMoreItemsFromSource: function (chunkSize) {
console.log(this._sourceDataItems);
let newItems = this._sourceDataItems.splice(0, chunkSize);
this.dataItems.push(newItems);
},
onLoadMoreItemsRequested: function (args) {
console.log("---load more item---");
const that = new WeakRef(this);
const listView = args.object;
if (this._sourceDataItems.length > 0) {
setTimeout(function () {
that.get().addMoreItemsFromSource(10);
listView.notifyLoadOnDemandFinished();
}, 1500);
args.returnValue = true;
} else {
args.returnValue = false;
listView.notifyLoadOnDemandFinished(true);
}
},
});
Search-view-model.js
_sourceDataItems: new ObservableArray(),
dataItems: new ObservableArray(),
initDataItems: function () {
var url = "https://adekunletestprojects.000webhostapp.com/skog/searchResults.php?search=" + encodeURIComponent("Adeyeye") + "&location=" + encodeURIComponent("Lagos");
fetch(url).then((response) => response.json()).then((res) => {
this._sourceDataItems = res.items;
this.addMoreItemsFromSource(6);
}).catch((err) => {
alert(err.message);
});
},
addMoreItemsFromSource: function (chunkSize) {
console.log(this._sourceDataItems);
let newItems = this._sourceDataItems.splice(0, chunkSize);
this.dataItems.push(newItems);
},
onLoadMoreItemsRequested: function (args) {
console.log("---load more item---");
const that = new WeakRef(this);
const listView = args.object;
if (this._sourceDataItems.length > 0) {
setTimeout(function () {
that.get().addMoreItemsFromSource(10);
listView.notifyLoadOnDemandFinished();
}, 1500);
args.returnValue = true;
} else {
args.returnValue = false;
listView.notifyLoadOnDemandFinished(true);
}
},
Search.js
exports.pageLoaded = function (args) {
const page = args.object;
var searchViewModel = new SearchViewModel();
page.bindingContext = searchViewModel;
searchViewModel.initDataItems();
searchViewModel.addMoreItemsFromSource(5);
}

ng2-file-upload single request clearQueue() not working

The uploader multiple files in one request so customized file uploads after getting a response using clearQueue() not working get single file only removed
core.js:3926 ERROR TypeError: Cannot read property 'abort' of
undefined
at FileUploaderCustom.push../node_modules/ng2-file-upload/file-upload/file-uploader.class.js.FileUploader.cancelItem
(file-uploader.class.js:112)
at FileItem.push../node_modules/ng2-file-upload/file-upload/file-item.class.js.FileItem.cancel
(file-item.class.js:38)
at FileUploaderCustom.push../node_modules/ng2-file-upload/file-upload/file-uploader.class.js.FileUploader.removeFromQueue
(file-uploader.class.js:85)
at FileItem.push../node_modules/ng2-file-upload/file-upload/file-item.class.js.FileItem.remove
(file-item.class.js:41)
at FileUploaderCustom.push../node_modules/ng2-file-upload/file-upload/file-uploader.class.js.FileUploader.clearQueue
(file-uploader.class.js:92)
at FileUploaderCustom.uploaderOnward.onSuccessItem (mandate-initial.component.ts:267)
at FileUploaderCustom.push../node_modules/ng2-file-upload/file-upload/file-uploader.class.js.FileUploader._onSuccessItem (file-uploader.class.js:396)
at XMLHttpRequest.xhr.onload [as __zone_symbol__ON_PROPERTYload] (fileUploader.ts:71)
at XMLHttpRequest.wrapFn (zone.js:1255)
at ZoneDelegate.invokeTask (zone.js:431)
customized file uploads .ts
export class FileUploaderCustom extends FileUploader {
constructor(
options: FileUploaderOptions
) {
super(options);
}
uploadAllFiles(): void {
// const _this = this;
const xhr = new XMLHttpRequest();
const sendable = new FormData();
const fakeItem: FileItem = null;
this.onBuildItemForm(fakeItem, sendable);
for (const item of this.queue) {
item.headers = [];
item.withCredentials = true;
item.formData = [];
item.isReady = true;
item.isUploading = true;
item.isUploaded = false;
item.isSuccess = false;
item.isCancel = false;
item.isError = false;
item.progress = 0;
item.index = void 0;
if (typeof item._file.size !== 'number') {
throw new TypeError('The file specified is no longer valid');
}
sendable.append('file', item._file, item.file.name);
}
if (this.options.additionalParameter !== undefined) {
Object.keys(this.options.additionalParameter).forEach((key) => {
sendable.append(key, this.options.additionalParameter[key]);
})
}
xhr.onerror = () => {
this.onErrorItem(fakeItem, null, xhr.status, null);
}
xhr.onabort = () => {
this.onErrorItem(fakeItem, null, xhr.status, null);
}
xhr.open('POST', this.options.url, true);
xhr.withCredentials = true;
if (this.options.headers) {
for (let _i = 0, _a = this.options.headers; _i < _a.length; _i++) {
const header = _a[_i];
xhr.setRequestHeader(header.name, header.value);
}
}
if (this.authToken) {
xhr.setRequestHeader(this.authTokenHeader, this.authToken);
}
xhr.onload = () => {
const headers = this._parseHeaders(xhr.getAllResponseHeaders());
const response = this._transformResponse(xhr.response, headers);
const gist = this._isSuccessCode(xhr.status) ? 'Success' : 'Error';
const method = '_on' + gist + 'Item';
for (const item of this.queue) {
this[method](item, response, xhr.status, headers);
}
this._onCompleteItem(this.queue[0], response, xhr.status, headers);
}
xhr.send(sendable);
}
}
responses
this.uploaderUpdate.onSuccessItem = (item, response, status, headers) => {
this.uploadResult = JSON.parse(response);
console.log(this.uploadResult)
if (this.uploadResult.rescode == "0000") {
this.uploaderUpdate.clearQueue();
this.editMyContainer = !this.editMyContainer;
this.toastyService.success(this.uploadResult.Description);
} else if (this.uploadResult.rescode == "0001") {
this.toastyService.error(this.uploadResult.ErrorDescription);
} else if (this.uploadResult.rescode == "0002") {
this.toastyService.error(this.uploadResult.ErrorDescription);
}
};

Categories