Overriding Promise implementation to Bluebird.Promise - javascript

I've got a scenario where promise will be undefined for some remote executions of a code base. Locally, it's running Node. Remotely, its running another runtime that doesn't have Promises. Bluebird works fine, but I'd like to override Promise for all files if it is undefined.
Something like:
import { Promise as BlueBirdPromise } from 'bluebird';
if (!Promise) {
Promise = BlueBirdPromise;
Promise.setScheduler((fn: any) => {
setTimeout(fn, 0);
});
}
The above code doesn't work as Promise and BlueBirdPromise are different types. I believe Promise is an interface in TS.
Is there a clean way to do this?
Example:
import { Promise as BlueBirdPromise } from 'bluebird';
BlueBirdPromise.setScheduler((fn: any) => {
setTimeout(fn, 0);
});
// eslint-disable-next-line
Promise = BlueBirdPromise;
Error:
polyfills.ts:13:1 - error TS2741: Property '[Symbol.species]' is missing in type 'typeof Bluebird' but required in type 'PromiseConstructor'.

We can accomplish this by overriding the Promise definition bound to the global object. This is done in the index.js file before any main code is executed.
Locally, Visual Studio Code will recognize Promise as its default type. However, when executed, this block will override the default Promise definition with that provided by Bluebird.
In this way, any use of Promise will use Bluebird over Node's definition. Or, in the case of the remote runtime not being node, provide an implementation where there is none.
import { Promise as BlueBirdPromise } from 'bluebird';
BlueBirdPromise.setScheduler((fn: any) => {
setTimeout(fn, 0);
});
global.Promise = <any>BlueBirdPromise;

Related

Return promises from Ember 2.16 Component Integration Tests Mocked action

I am creating tests for my Ember 2.16 application, and running into an issue where the code is dependent on a promise being returned from an external action.
const promise = this.sendAction('action')
promise.then(() => {
//do stuff
});
A majority of my code is based in these .then and .catch conditionals on the promise, so I want to be able to return a promise that was successful and that failed. I have heard of Sinon, but unfortunately it is only for Ember 3.4 and above.
test('', function(assert){
this.set('action', () => {
// do assertions
return new Promise(() => {return true} );
});
});
Inside my integration test I am able to mock out the action, but I run into the "promise" being undefined. I have attempted to return Text, or other values, but when putting a debugger into the component the promise is always undefined.
I can get around this by adding a conditional that checks to see if there is a promise, but since the majority of my code is inside these .then and .catchconditionals I want my tests to step through these to increase the code coverage.
How would I return a promise from a mocked out action in an Integration Test?
You can stub your call to sendAction like so in your integration test:
test('', function(assert) {
this.sendAction = () => RSVP.resolve(true);
this.render(hbs`{{some-component sendAction=sendAction}}`);
});
This will return a promise as your code expects.
I recommend using the RSVP library in cases where you need to use promises.
It turns out I was returning the promise incorrectly.
return new Promise((reject) => {
reject(true);
});
Was able to return the promise as "rejected".

Can't catch an unhandled Promise rejection from 3rd party library

I'm using a 3rd parth library to make an async call in my nodejs backend code. There's an unhandled promise rejection coming from this call which I'm having trouble catching. (It brings down my node app.)
Based on the input passed, it's expected to fail sometimes:
exports.getSomeData = (input) => {
console.log('GETTING DATA...')
return ThirdPartyLib.makeAsyncCall(input).then((result) => {
console.log('SUCCESS');
return result;
},(rejection) => {
console.log('REJECTED');
return {};
}).catch(error => {
console.log('ERROR');
return {};
});
}
But none of the REJECTED/ERROR messages print when it fails. I just see a console message from the lib: Unhandled rejection at: Promise and my app goes down.
Am I missing anything in the way I handle the non-happy path?
Is it possible for the library code to do something that the above WOULDN'T catch?
Is it possible for the library code to do something that the above WOULDN'T catch?
Sure, it just has to create a Promise (e.g. by calling an async function) without chaining it into the promise chain (aka without awaiting it):
async makeAsyncCall(data) {
Promise.reject("Possible");
}
So yes, the library you are using should either await that detached promise or it should attach an error handler to it (and handle / purposely ignore the error). It's not your fault.
Aside from the double rejection handler (which is pointless, just use catch()), your code should just work.
So given that you are seeing that error, this means that the library you are using has a bug.

How does using async/await differ from using Promises?

Recently I started using (Async & Await). Before this, I used Promise to make my process Asynchronous. Like:
example.firstAsyncRequest()
.then(firstResponse => {
return example.secondAsyncRequest(firstResponse)
})
.then(secondResponse => {
return example.thirdAsyncRequest(secondResponse)
})
.then(result => {
console.log(result)
})
.catch(err => {
console.log(err)
})
Now I am achieving this like:
try {
const firstResponse = await example.firstAsyncRequest();
const secondResponse = await example.secondAsyncRequest(firstResponse);
const thirdAsyncRequest = await example.thirdAsyncRequest(secondResponse);
console.log(thirdAsyncRequest)
}
catch (error) {
// Handle error
}
In both, the code-block method executes one after another and finally throws an error if any and gets caught by catch block. My question is, is this only a difference of syntax? Please explain or suggest me any link to understand this better.
Thank You
Is there only difference of syntax?
Yes. Your examples are functionally equivalent except that your second example is missing
console.log(thirdAsyncRequest);
...after the third await. (That variable really should be result to match the first code block, or thirdResponse to match the other two response variables).
async/await is syntactic sugar around promise creation and consumption. It's really helpful sugar, but that's all it is. async functions return promises. await expressions let you wait for a promise to settle, either getting the fulfillment value if it's fulfilled or throwing an error if it's rejected. (Since rejections are errors, you can use try/catch to handle them.) An uncaught error in an async function (whether a synchronous error or a promise rejection observed by await) causes the promise the async function returned to be rejected with that error. Otherwise, the function's promise is resolved to whatever the function's code returns: if it returns a non-thenable, the promise is fulfilled with that value; if it returns a thenable, the promise is fulfilled or rejected based on the settlement of that thenable.
(Re "resolve" vs. "fulfill" and such, I've written up this post on promise terminology.)

Node - ReferenceError: Promise is not defined

I am starting out with Node. Sorry for what probably is a stupid question.
Trying to understand why the below code throws an error: ReferenceError: Promise is not defined
allAccountFixtures: ['account-customer-joe', 'account-partner-sam', 'account-partner-jane', 'account-admin-jill'],
allProductFixtures: ['product-123', 'product-234', 'product-345', 'product-456'],
...
loadBasicFixtures: (Api) => {
return Promise.all([
Support.importRecords(Api.accountsAPI, Support.allAccountFixtures),
Support.importRecords(Api.productsAPI, Support.allProductFixtures)
]);
},
My APIs are defined elsewhere as:
this.accountsAPI = app.service('/api/accounts');
this.productsAPI = app.service('/api/products');
The import function is:
importRecords: (feathersService, fixtureNames) => {
// Wrap in an array if there's only one.
if (!(fixtureNames instanceof Array)) { fixtureNames = [fixtureNames]; }
// Create a separate promise for each JSON fixture to load the JSON from a
// file and send it to feathers.create(). Don't execute yet.
var promises = fixtureNames.map(fixtureName => {
var filePath = `test/fixtures/json/${fixtureName}.json`;
// console.log(`-> Loading JSON fixture: ${filePath}`);
return fs.readFileAsync(filePath, 'utf8')
.then((jsonString) => {
return JSON.parse(jsonString);
}).then((json) => {
return feathersService.create(json);
});
});
// Wrap all fixture loading promises inside a single outer promise that will
// fire when all of the child promises are complete.
return Promise.all(promises);
},
Don't know whether the supplied information is sufficient to advise what is happening. I looked up the concept of a "promise" and that's pretty much it. Perhaps you could point to the right direction. The documentation mentions resolve and reject.
I'll make my comment into an answer since it solved your issue.
Some older versions of node.js do not have promises built-in and to use promises with them requires loading a third party library that adds promise support.
If you upgrade to any 4.x version of node.js or newer, you will have promises built-in to node.js.
You need to import and require Promise
npm install promise --save
Then
var Promise = require('promise');

What happens if i reject / resolve multiple times in Kriskowal's q?

I'm studying the promises pattern and using kriskowal's q for node.js,
having this snippet:
var deferred = Q.defer();
try {
messageData = JSON.parse(message);
} catch (e) {
global.logger.warn('Error parsing JSON message.');
deferred.reject(e);
}
...
if (some_reason)
deferred.resolve(something);
...
return deferred.promise;
What if both the parser fails and some_reason is true?
Will the execution procede from rejecting through resolving and both promise's method be called at different times, thus generating a bug?
Should i avoid to call reject/resolve multiple times?
Since promises can only resolve once (to either fulfilled or rejected), the first resolution wins and any further calls will be ignored. From the docs:
In all cases where a promise is resolved (i.e. either fulfilled or rejected), the resolution is permanent and cannot be reset. Attempting to call resolve, reject, or notify if promise is already resolved will be a no-op.
Should i avoid to call reject/resolve multiple times?
You can even design your application letting two methods "race" against each other to resolve a deferred, but in general it should be avoided to reduce confusion of a reader.
original post here
see github gist: reuse_promise.js
/*
reuse a promise for multiple resolve()s since promises only resolve once and then never again
*/
import React, { useEffect, useState } from 'react'
export default () => {
const [somePromise, setSomePromise] = useState(promiseCreator())
useEffect(() => {
somePromise.then(data => {
// do things here
setSomePromise(promiseCreator())
})
}, [somePromise])
}
const promiseCreator = () => {
return new Promise((resolve, reject) => {
// do things
resolve(/*data*/)
})
}

Categories

Resources