I am struggling with the Response of the Javascript fetch() method. What is my objective: a) to send multiple lines to the backend to save those to a database and b) get a guid in return for further processing.
I succeed in objective a (save to database), but the return message fails to materialise. Response.ok is true, but no message is part of the return message.
What should I do to accomplish this?
My javascript is:
function saveAll(event) {
event.preventDefault();
var newDeelnemers = new Array();
var lijst = document.querySelectorAll('#tblDeelnemers tbody tr')
lijst.forEach(function (dnmr) {
var row = dnmr;
var deelnemer = {};
var nDnmr = row.children;
//deelnemer.Id = nDnmr[0].innerHTML;
deelnemer.FamilielidFirstName = nDnmr[0].innerHTML;
deelnemer.Achternaam = nDnmr[1].innerHTML;
deelnemer.DOB = nDnmr[2].innerHTML;
deelnemer.Programma = nDnmr[3].innerHTML;
deelnemer.EetMee = nDnmr[4].firstChild.checked;
deelnemer.Dieet = nDnmr[5].innerHTML;
deelnemer.Bedrag = nDnmr[6].innerHTML;
newDeelnemers.push(deelnemer);
});
fetch("/Familiedag/Registreer", {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(newDeelnemers)
}).then(function (response) {
console.log('eerste keer: ' + response);
if (response.ok) {
alert('De registratie is gelukt');
//redirect("/Familiedag/RegistreerConfirm?")
}
});
}
The controller
[HttpPost]
public IActionResult Registreer([FromBody] List<FdDeelnemer> newDeelnemers)
{
if (newDeelnemers.Count == 0)
{
return null;
}
Guid registratieGuid = Guid.NewGuid();
foreach (var ndn in newDeelnemers)
{
FdDeelnemer VM = new FdDeelnemer();
VM.RegistratieGuid = registratieGuid;
VM.FamilielidFirstName = ndn.FamilielidFirstName;
VM.Achternaam = ndn.Achternaam;
VM.EetMee = ndn.EetMee;
VM.Dieet = ndn.Dieet;
VM.Programma = ndn.Programma;
VM.DOB = ndn.DOB;
VM.Bedrag = ndn.Bedrag;
VM.CreatedBy = User.Identity.Name;
VM.CreatedOn = DateTime.UtcNow;
_context.Add(VM);
}
Guid geregistreerdeDeelnemers = registratieGuid;
return Json(geregistreerdeDeelnemers);
}
add another .then that return the json
fetch("/echo/json/", {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
"tes": "data"
})
}).then(function(response) {
return response.json();
}).then(function(json) {
console.log('eerste keer: ', json);
alert('De registratie is gelukt');
//redirect("/Familiedag/RegistreerConfirm?")
});
You can try to return it like that:
return Json(new { AnythingYouWant = geregistreerdeDeelnemers });
I've been working on a script that creates and updates stuff with the ExactOnline API.
when I run the script locally everything works fine but when I try to use it on a platform such as Zapier or n8n it doesn't work as intended.
on Zapier it only runs just before it does a fetch request
this my code that I use in zapier:
var token = 'token';
var divisionid = 'divisionid';
var AMRelatieData = {
"Name": "company name",
"City": "city name",
"Website": "website.com"
};
var AMContactData = {
"FirstName": "firstname",
"LastName": "lastname",
"City": "name city"
};
var testrlid;
async function actionHandeler(actionValue) {
var action = actionValue;
if (action == "cp_maken_&_relatie_maken") {
var maakRelatieWaarde = await maakRelatie(AMRelatieData);
var POSTrelatieID = maakRelatieWaarde;
AMContactData.Account = POSTrelatieID;
var maakContactwaarde = await maakContact(AMContactData);
var POSTcontactID = maakContactwaarde;
testcpid = POSTcontactID;
testrlid = POSTrelatieID;
return ('maakContactwaarde succes');
}
//functions
async function updateRelatie(updateData, relatieId) {
var UpdateRelatiePUT = await PUTreq(1, updateData, relatieId);
console.log(UpdateRelatiePUT);
return ("updateRelatie succes");
}
async function maakRelatie(createData) {
var relatieId;
console.log('maakRelatie: ');
var maakRelatiePOST = await POSTreq(1, createData);
console.log('maakRelatieFunc:' + JSON.stringify(maakRelatiePOST));
return await maakRelatiePOST.d.ID;
}
async function maakContact(createData) {
var contactId;
var maaktcontactPOST = await POSTreq(2, createData);
console.log('maaktcontactFunc:' + JSON.stringify(maaktcontactPOST));
var jsonData = {
MainContact: maaktcontactPOST.d.ID
};
var relatieIdUpdate = createData.Account;
await updateRelatie(jsonData, relatieIdUpdate);
}
async function POSTreq(type, DATA) {
console.log('postreq');
var POSTendpoint = 'https://start.exactonline.nl/api/v1/'+ divisionid +'/crm/';
if (type == 1) {
POSTendpoint += 'Accounts';
}
if (type == 2) {
POSTendpoint += 'Contacts';
}
var outputPOST;
console.log(DATA);
await fetch(POSTendpoint, {
method: "POST",
headers: {
'Accept': 'application/json',
'Authorization': 'Bearer ' + token,
'Content-Type': 'application/json'
},
body: JSON.stringify(DATA)
}).then(response => {
return response.json();
}).then(jsonResponse => {
var responseOut = jsonResponse;
outputPOST = responseOut;
}).catch(error => {
console.log(error);
});
return outputPOST;
}
async function PUTreq(type, DATA, id) {
var PUTendpoint = 'https://start.exactonline.nl/api/v1/'+ divisionid +'/crm/';
console.log('put data');
console.log(id);
console.log('data' + DATA);
console.log(type);
if (type == 1) {
PUTendpoint += "Accounts(guid'" + id + "')";
}
if (type == 2) {
PUTendpoint += "Contacts(guid'" + id + "')";
}
console.log(PUTendpoint);
console.log(PUTendpoint);
await fetch(PUTendpoint, {
method: 'PUT',
headers: {
'Content-Type': 'application/json',
'Authorization': 'Bearer ' + token
},
body: JSON.stringify(DATA)
});
}
}
async function actionHandlerFunc(){
console.log("begin");
await actionHandeler("cp_maken_&_relatie_maken");
return ("done did sum stuff");
};
output = [actionHandlerFunc()]
I have a question about the code. Probably the solution is very simple, but I'm taking the first step in JavaScript and it is not obvious to me.
I have some backend ready, postman sending POST is ok. So backend is fine.
I wrote a simple application in which after pressing the button saves the given data in the database.
Unfortunately, this doesn't work with the debugger, everything is fine. However, by clicking the button in the view something is wrong and no fetch is called. The object is not saving to the database.
Please help.
Api = function() {
this.header = new Headers({
'Accept': 'application/json',
'Content-Type': 'application/json'
})
};
Api.prototype.buildUrl = function(id) {
return "http://localhost:3000/db/shop_name/" + id;
};
Api.prototype.post = function(id, data) {
const urlPost = api.buildUrl(id.value);
return fetch(urlPost, {
method: "post",
body: JSON.stringify(data),
headers: this.header
})
.then(res => res.json())
.then(res => {
console.log("Dodałem użytkownika:");
console.log(res);
})
};
Api.prototype.get = function(id) {
//const urlGet = api.buildUrl(id);
return fetch(id, {
method: "GET",
})
.then(resp => {
alert(resp.json());
return resp.json();
})
};
Api.prototype.getAlll = function() {
return fetch(url, {
method: "GET"
})
.then(resp => {
alert(resp.json());
return resp.json()
})
};
Api.prototype.update = function(id, data) {
const url = api.buildUrl(id);
return fetch(url, {
method: "PUT",
body: JSON.stringify(data)
})
.then(resp => {
return resp.json()
.catch(error => {
let notFound = "The server can not find requested resource";
document.getElementById("stars").innerHTML = notFound + error.status;
})
})
};
Api.prototype.addProduct = function(id, data) {
return this.post(id, data);
};
Api.prototype.deleteProduct = function(id) {
return this.delete(id);
};
Api.prototype.updateProduct = function(id, data) {
return this.update(id, data);
};
Api.prototype.getProduct = function(id) {
return this.get(id);
};
Api.prototype.getAllProducts = function() {
return this.getAlll;
};
const Main = function() {
this.id = document.getElementById("id");
this.addCount = document.getElementById("count");
this.addName = document.getElementById("name");
this.addPrice = document.getElementById("price");
};
Main.prototype.add = function() {
// const ido = this.id.value;
const data = {
"price": this.addPrice.value,
"name": this.addName.value,
"count": this.addCount.value,
};
// let id = api.buildUrl(this.id.value);
api.addProduct(this.id, data);
};
Main.prototype.update = function() {
const data = {
"price": this.price,
"name": this.name,
"count": this.count,
};
api.updateProduct(id, data);
};
Main.prototype.delete = function() {
let id = api.buildUrl(this.id);
api.deleteProduct(id);
};
Main.prototype.get = function() {
let id = api.buildUrl(this.id.value);
api.getProduct(id);
};
Main.prototype.getAll = function() {
api.getAllProducts();
};
const api = new Api();
const main = new Main();
let addButton = document.getElementById('postBtn');
addButton.addEventListener('click', function() {
main.add();
});
/*
addButton.addEventListener("click",main.add.bind(main));
*/
let updateButton = document.getElementById("updateBtn");
updateButton.addEventListener("click", function() {
main.update();
});
let deleteButton = document.getElementById("deleteBtn");
deleteButton.addEventListener("click", function() {
main.delete();
});
let getButton = document.getElementById("getBtn");
getButton.addEventListener("click", function() {
main.get();
});
let getAllButton = document.getElementById("getAllBtn");
getAllButton.addEventListener("click", function() {
let tst = main.getAll();
console.log(tst);
});
I'm getting 'client' undefined from a library I am using for firebase rest transactions, and it is one I am pretty sure I used before with no problems. When I look in the library (the intellij websphere debugger takes me to a typescript file, must be map aware), I see this.client..., in a class method which I am calling, so this should definitely be defined.
So then I grabbed a different library, that happens to be all one file so I could put it directly in my src/ folder, (why fix a flat when there are other broken wheels lying around, right?) and .. same thing (only this time it is this.url because different library).
The basic structure does work, because: (compare commented code to inline Promise)
class FirebaseDb {
constructor() {}
async tx(command, path, payload, queryParams) {
const dbcmd = FirebaseDb.ref[FirebaseDb.fbcrest[command]]
/*const unary = (command === 'get' || commmand === 'delete')
const operation = await (unary?
dbcmd(path, queryParams):
dbcmd(path, payload, queryParams))*/
const res = await new Promise((r,e)=>setTimeout(
()=>{
console.log('inner this: ' + this);
r({foo:'bar'})
}, 1000))
const operation = {ok: true, body: res}
if(!operation.ok)
throw new Error(`[FirebaseDb] ${FirebaseDb.fbcrest[command]} - error with TX. (status ${operation.status}: ${operation.statusText})`)
return operation.body
}
That promise works just fine. I hit my api url and get {"foo":"bar"} a second later. The console doesn't show an undefined this, it reports inner this: [object Object].
So here's the full two files (that snippet was from firebaseDb.js, which will not show in the below because it was just a demonstration):
firebaseDb.js
import restFirebase from './restful-firebase'
import config from 'config'
/* FirebaseDb is a specific Model Db Firebase object. It receives REST calls
and converts them to firebase REST calls, executes them on a firebase
connection, returning the result or erroring out if there is an error. this
could be swapped out with a similar one for MongoDB, etc */
class FirebaseDb {
constructor() {}
async tx(command, path, payload, queryParams) {
const dbcmd = FirebaseDb.ref[FirebaseDb.fbcrest[command]]
const unary = (command === 'get' || commmand === 'delete')
const operation = await (unary?
dbcmd(path, queryParams):
dbcmd(path, payload, queryParams))
if(!operation.ok)
throw new Error(`[FirebaseDb] ${FirebaseDb.fbcrest[command]} - error with TX. (status ${operation.status}: ${operation.statusText})`)
return operation.body
}
}
FirebaseDb.fbcrest = {
get: 'get',
put: 'set',
patch: 'update',
post: 'push',
delete: 'remove'
}
FirebaseDb.db = restFirebase.factory(config.firebase.project)
FirebaseDb.ref = FirebaseDb.db({
paths: '/',
auth: config.firebase.auth
})
export default FirebaseDb
restful-firebase.js
(modified npm i rest-firebase, accepts path in tx calls, no use strict for debugging):
import request from 'request'
const TIMEOUT = 5000;
const baseRequest = request.defaults({timeout: TIMEOUT, json: true});
const VALID_ID = /^[-0-9a-zA-Z]{2,}$/;
const VALID_URL = /^https?:\/\/[\da-z\.-]+(\:\d+)?\/?$/;
const ERR_INVALID_ID = 'Invalid Firebase id.';
const ERR_NO_SECRET = 'A Firebase secret is required for this operation.';
class ResponseError extends Error {
constructor(opts, resp, body) {
super(resp.statusMessage);
this.name = 'ResponseError';
this.url = opts.url;
this.method = opts.method;
this.status = resp.statusCode;
this.authDebug = resp.headers['x-firebase-auth-debug'];
this.body = body;
}
}
class Request {
constructor(opts) {
this.rootPath = trimPath(opts.rootPath);
this.url = opts.url;
this.auth = opts.auth;
this.$logger = opts.logger || console;
}
toString() {
return Request.fixUrl(this.url);
}
static fixUrl(url) {
return url.endsWith('.json') ? url : `${url}.json`;
}
process(url, method, qs, payload) {
return new Promise((resolve, reject) => {
const opts = {
url: Request.fixUrl(url),
method: method,
qs: Object.assign({auth: this.auth}, qs)
};
if (payload !== undefined) {
opts.body = payload;
}
baseRequest(opts, (err, resp, body) => {
if (err) {
reject(err);
return;
}
const debugMessage = resp.headers['x-firebase-auth-debug'];
if (debugMessage) {
this.$logger.warn(debugMessage);
}
if (resp.statusCode >= 300) {
reject(new ResponseError(opts, resp, body));
return;
}
resolve(body);
});
});
}
rules(rules) {
if (!this.auth) {
return Promise.reject(new Error(ERR_NO_SECRET));
}
const opts = {
'method': 'GET',
'url': `${this.rootPath}/.settings/rules.json`,
'qs': {auth: this.auth}
};
return new Promise((resolve, reject) => {
if (rules) {
opts.method = 'PUT';
opts.body = rules;
opts.json = typeof(rules) === 'object';
}
request(opts, (err, resp, body) => {
if (err) {
reject(err);
return;
}
if (resp.statusCode >= 300) {
reject(new ResponseError(opts, resp, body));
return;
}
resolve(body);
});
});
}
get(path, qs) {
let url = this.url
if(path)
url += '/' + path
return this.process(url, 'GET', qs);
}
set(path, payload, qs) {
let url = this.url
if(path)
url += '/' + path
return this.process(url, 'PUT', qs, payload);
}
update(path, payload, qs) {
let url = this.url
if(path)
url += '/' + path
if (url.endsWith('/.json')) {
// no-op
} else if (url.endsWith('.json')) {
url = `${url.slice(0, -5)}/.json`;
} else if (url.endsWith('/')) {
url = `${url}.json`;
} else {
url = `${url}/.json`;
}
return this.process(url, 'PATCH', qs, payload);
}
push(path, patch, qs) {
let url = this.url
if(path)
url += '/' + path
return this.process(url, 'POST', qs, patch);
}
remove(path, qs) {
let url = this.url
if(path)
url += '/' + path
return this.process(url, 'DELETE', qs);
}
}
function trimPath(path) {
return path.replace(/\/+$/, '');
}
/**
* Create a firebase rest client factory.
*
* The clients will be bound to a firebase ID. You then can use relative path
* to create references to entities in your Firebase DB.
*
* Usage:
*
* const restFirebase = require('rest-firebase');
* const firebase = restFirebase.factory('some-id');
* const ref = firebase({paths: 'some/path', auth: 'some-oauth-token'});
*
* // you can pass parameters
* // (see https://www.firebase.com/docs/rest/api/#section-query-parameters)
* ref.get({shallow: true}).then(value => {
* // ...
* });
*
* #param {string} target Firebase ID or URL
* #return {function}
*
*/
function restFirebaseFactory(target) {
let rootPath;
if (VALID_URL.test(target)) {
rootPath = trimPath(target);
} else if (VALID_ID.test(target)) {
rootPath = `https://${target}.firebaseio.com`;
} else {
throw new Error(ERR_INVALID_ID);
}
function restFirebase(opts) {
const relPaths = opts && opts.paths || '';
const url = [rootPath].concat(relPaths).join('/');
return new Request(
Object.assign({}, opts, {rootPath, url})
);
}
return restFirebase;
}
exports.Request = Request;
exports.factory = restFirebaseFactory;
some of the "magic" that might be involved:
my .babelrc
{
"presets": ["latest"]
}
my gulpfile:
const gulp = require('gulp');
const babel = require('gulp-babel');
const clean = require('gulp-rimraf');
const dest = 'dist'
gulp.task('src', ['clean'], () => {
return gulp.src(['server.js', 'src/**/*.js'])
.pipe(babel({
plugins: ['syntax-async-functions','transform-async-to-generator', 'transform-runtime']
}))
.pipe(gulp.dest(dest));
});
gulp.task('node_modules', ['clean', 'src'], () => {
return gulp.src(['node_modules/vue/dist/vue.js', 'node_modules/vue-router/dist/vue-router.js', 'node_modules/vuex/dist/vuex.js'])
.pipe(gulp.dest(dest+'/node_modules'));
});
gulp.task('clean', () => {
gulp.src(dest+'/*', {read:false})
.pipe(clean())
})
gulp.task('default', ['node_modules', 'src'])
those do this to restful-firebase.js:
'use strict';
var _typeof2 = require('babel-runtime/helpers/typeof');
var _typeof3 = _interopRequireDefault(_typeof2);
var _assign = require('babel-runtime/core-js/object/assign');
var _assign2 = _interopRequireDefault(_assign);
var _promise = require('babel-runtime/core-js/promise');
var _promise2 = _interopRequireDefault(_promise);
var _createClass2 = require('babel-runtime/helpers/createClass');
var _createClass3 = _interopRequireDefault(_createClass2);
var _getPrototypeOf = require('babel-runtime/core-js/object/get-prototype-of');
var _getPrototypeOf2 = _interopRequireDefault(_getPrototypeOf);
var _classCallCheck2 = require('babel-runtime/helpers/classCallCheck');
var _classCallCheck3 = _interopRequireDefault(_classCallCheck2);
var _possibleConstructorReturn2 = require('babel-runtime/helpers/possibleConstructorReturn');
var _possibleConstructorReturn3 = _interopRequireDefault(_possibleConstructorReturn2);
var _inherits2 = require('babel-runtime/helpers/inherits');
var _inherits3 = _interopRequireDefault(_inherits2);
var _request = require('request');
var _request2 = _interopRequireDefault(_request);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
var TIMEOUT = 5000;
var baseRequest = _request2.default.defaults({ timeout: TIMEOUT, json: true });
var VALID_ID = /^[-0-9a-zA-Z]{2,}$/;
var VALID_URL = /^https?:\/\/[\da-z\.-]+(\:\d+)?\/?$/;
var ERR_INVALID_ID = 'Invalid Firebase id.';
var ERR_NO_SECRET = 'A Firebase secret is required for this operation.';
var ResponseError = function (_Error) {
(0, _inherits3.default)(ResponseError, _Error);
function ResponseError(opts, resp, body) {
(0, _classCallCheck3.default)(this, ResponseError);
var _this = (0, _possibleConstructorReturn3.default)(this, (ResponseError.__proto__ || (0, _getPrototypeOf2.default)(ResponseError)).call(this, resp.statusMessage));
_this.name = 'ResponseError';
_this.url = opts.url;
_this.method = opts.method;
_this.status = resp.statusCode;
_this.authDebug = resp.headers['x-firebase-auth-debug'];
_this.body = body;
return _this;
}
return ResponseError;
}(Error);
var Request = function () {
function Request(opts) {
(0, _classCallCheck3.default)(this, Request);
this.rootPath = trimPath(opts.rootPath);
this.url = opts.url;
this.auth = opts.auth;
this.$logger = opts.logger || console;
}
(0, _createClass3.default)(Request, [{
key: 'toString',
value: function toString() {
return Request.fixUrl(this.url);
}
}, {
key: 'process',
value: function process(url, method, qs, payload) {
var _this2 = this;
return new _promise2.default(function (resolve, reject) {
var opts = {
url: Request.fixUrl(url),
method: method,
qs: (0, _assign2.default)({ auth: _this2.auth }, qs)
};
if (payload !== undefined) {
opts.body = payload;
}
baseRequest(opts, function (err, resp, body) {
if (err) {
reject(err);
return;
}
var debugMessage = resp.headers['x-firebase-auth-debug'];
if (debugMessage) {
_this2.$logger.warn(debugMessage);
}
if (resp.statusCode >= 300) {
reject(new ResponseError(opts, resp, body));
return;
}
resolve(body);
});
});
}
}, {
key: 'rules',
value: function rules(_rules) {
if (!this.auth) {
return _promise2.default.reject(new Error(ERR_NO_SECRET));
}
var opts = {
'method': 'GET',
'url': this.rootPath + '/.settings/rules.json',
'qs': { auth: this.auth }
};
return new _promise2.default(function (resolve, reject) {
if (_rules) {
opts.method = 'PUT';
opts.body = _rules;
opts.json = (typeof _rules === 'undefined' ? 'undefined' : (0, _typeof3.default)(_rules)) === 'object';
}
(0, _request2.default)(opts, function (err, resp, body) {
if (err) {
reject(err);
return;
}
if (resp.statusCode >= 300) {
reject(new ResponseError(opts, resp, body));
return;
}
resolve(body);
});
});
}
}, {
key: 'get',
value: function get(path, qs) {
var url = this.url;
if (path) url += '/' + path;
return this.process(url, 'GET', qs);
}
}, {
key: 'set',
value: function set(path, payload, qs) {
var url = this.url;
if (path) url += '/' + path;
return this.process(url, 'PUT', qs, payload);
}
}, {
key: 'update',
value: function update(path, payload, qs) {
var url = this.url;
if (path) url += '/' + path;
if (url.endsWith('/.json')) {
// no-op
} else if (url.endsWith('.json')) {
url = url.slice(0, -5) + '/.json';
} else if (url.endsWith('/')) {
url = url + '.json';
} else {
url = url + '/.json';
}
return this.process(url, 'PATCH', qs, payload);
}
}, {
key: 'push',
value: function push(path, patch, qs) {
var url = this.url;
if (path) url += '/' + path;
return this.process(url, 'POST', qs, patch);
}
}, {
key: 'remove',
value: function remove(path, qs) {
var url = this.url;
if (path) url += '/' + path;
return this.process(url, 'DELETE', qs);
}
}], [{
key: 'fixUrl',
value: function fixUrl(url) {
return url.endsWith('.json') ? url : url + '.json';
}
}]);
return Request;
}();
function trimPath(path) {
return path.replace(/\/+$/, '');
}
/**
* Create a firebase rest client factory.
*
* The clients will be bound to a firebase ID. You then can use relative path
* to create references to entities in your Firebase DB.
*
* Usage:
*
* const restFirebase = require('rest-firebase');
* const firebase = restFirebase.factory('some-id');
* const ref = firebase({paths: 'some/path', auth: 'some-oauth-token'});
*
* // you can pass parameters
* // (see https://www.firebase.com/docs/rest/api/#section-query-parameters)
* ref.get({shallow: true}).then(value => {
* // ...
* });
*
* #param {string} target Firebase ID or URL
* #return {function}
*
*/
function restFirebaseFactory(target) {
var rootPath = void 0;
if (VALID_URL.test(target)) {
rootPath = trimPath(target);
} else if (VALID_ID.test(target)) {
rootPath = 'https://' + target + '.firebaseio.com';
} else {
throw new Error(ERR_INVALID_ID);
}
function restFirebase(opts) {
var relPaths = opts && opts.paths || '';
var url = [rootPath].concat(relPaths).join('/');
return new Request((0, _assign2.default)({}, opts, { rootPath: rootPath, url: url }));
}
return restFirebase;
}
exports.Request = Request;
exports.factory = restFirebaseFactory;
and specifically the section of code where this is undefined, throwing an error is the 3rd line in:
key: 'get',
value: function get(path, qs) {
var url = this.url;
if (path) url += '/' + path;
return this.process(url, 'GET', qs);
}
Usually it is safe to assume that the method is called as a callback in such case, this can be fixed by using arrow function or bind. Object methods cannot be detached from the object if they aren't bound.
Considering that
const dbcmd = FirebaseDb.ref[FirebaseDb.fbcrest[command]]
is the place of interest, it should be
const dbcmd = FirebaseDb.ref[FirebaseDb.fbcrest[command]].bind(FirebaseDb.ref)
or
const dbcmd = (...args) => FirebaseDb.ref[FirebaseDb.fbcrest[command]](...args)
Given the following object:
var MyObject = function(field1, field2) {
this.field1 = field1;
this.field2 = field2;
}
MyObject.prototype.setField1 = functioin(field1) {
this.field1 = field1;
}
MyObject.prototype.apply = function() {
...
this.setField1("hello");
log("field1: " + this.field1); // field1 has not been set to "hello"
}
I want to change the value of field1... but the code above doesn't seem to work. Am I missing something? Tx.
EDIT
OK, it's worth providing you with the real case. Here below is my customization of Swagger for dealing with JWT:
var TokenAuthorization = function(appId, value) {
this.appId = appId;
this.value = value;
this.type = null;
this.expirationTime = null;
};
TokenAuthorization.prototype.set = function(value, type, expirationTime) {
this.value = value;
this.type = type;
this.expirationTime = expirationTime;
};
TokenAuthorization.prototype.apply = function(obj, authorizations) {
var now = Math.round(new Date().getTime() / 1000);
var appId = this.appId;
var value = this.value;
var type = this.type;
var expirationTime = this.expirationTime;
if (value == null || (type == "browse" && this.expirationTime <= now)) {
var baseUrl = "http://localhost:9000/auth";
$.ajax({
type: "GET",
url: baseUrl + "/apps/" + appId + "/apikey"
}).done(function(data) {
$.ajax({
type: "POST",
data: JSON.stringify({ principal: appId, secret: data.apiKey }),
url: baseUrl + "/apps/credentials",
contentType: "application/json"
}).done(function(data) {
value = data.token;
$.ajax({
type: "GET",
headers: { "Authorization": "Token " + value },
url: baseUrl + "/users/credentials"
}).done(function(data) {
type = data.token.header.typ.split('/')[1],
expirationTime = data.token.claims.exp
})
})
});
}
this.set(value, type, expirationTime);
log("token: " + this.value); // value is null
log("typ: " + this.type); // type is null
log("exp: " + this.expirationTime); // expirationTime is null
obj.headers["Authorization"] = "Token " + this.value;
return true;
};
The code above performs three REST calls to obtain a token and let the client application browse thru the API. Finally, here is how I create the object:
window.authorizations.add("authToken", new TokenAuthorization("myApp", null));
Since I pass null as the second parameter (token), I need to get a browse token for the current client app. That's it.
I guess the problem has to do with the fact I'm performing async REST calls.
OK, after some debugging I figured out what problem was. ajax is async, so apply returns immediately and of course the data is still null.
Rewriting the code like this solved the problem:
var e = (typeof window !== 'undefined' ? window : exports);
var TokenAuthorization = function(appId, token, type, expirationTime) {
this.appId = appId;
this.token = token;
this.type = type;
this.expirationTime = expirationTime;
this.locked = false
};
TokenAuthorization.prototype.lock = function() {
this.locked = true;
};
TokenAuthorization.prototype.unlock = function() {
this.locked = false;
};
TokenAuthorization.prototype.apply = function(obj, authorizations) {
var now = Math.round(new Date().getTime() / 1000);
if (!this.locked && (this.token == null || (this.type == "browse" && this.expirationTime <= now))) {
var baseUrl = obj.url.split("api-docs")[0] + "auth";
var appId = this.appId;
this.lock();
$.ajax({
type: "GET",
url: baseUrl + "/apps/" + appId + "/apikey"
}).done(function(result) {
$.ajax({
type: "POST",
data: JSON.stringify({ principal: appId, secret: result.apiKey }),
url: baseUrl + "/apps/credentials",
contentType: "application/json"
}).done(function(result) {
var token = result.token;
$.ajax({
type: "GET",
headers: { "Authorization": "Token " + token },
url: baseUrl + "/users/credentials"
}).done(function(result) {
e.authorizations.add("authToken", new TokenAuthorization(
appId, token,
result.token.header.typ.split('/')[1],
result.token.claims.exp
));
log("token: " + token);
obj.headers["Authorization"] = "Token " + token;
})
})
});
} else if (!this.locked) {
obj.headers["Authorization"] = "Token " + this.token;
}
return true;
};
This way, if a token already exists, it is used as is, otherwise a new one will be set once the REST calls complete.