The following code evaluates to false in Chrome: Version 49.0.2623.75 (64-bit)
var USE_NATIVE = !!function(){
try {
// correct subclassing with @@species support
var promise = $Promise.resolve(1)
, FakePromise = (promise.constructor = {})[require('./_wks')('species')] = function(exec){ exec(empty, empty); };
// unhandled rejections tracking support, NodeJS Promise without it fails @@species test
return (isNode || typeof PromiseRejectionEvent == 'function') && promise.then(empty) instanceof FakePromise;
} catch(e){ /* empty */ }
}();
I'm not an expert, but what I can said is, if the environment provides the fetch API, we should consider promises available, because any call to fetch() will return a "native" instance instead of a an instance using the polyfill.
Make sense?
@dendril Having fetch and having a Promise constructor does not mean that the Promise implementation is spec compliant. The goal of a polyfill is to ensure spec compliance across the board. I believe it's Chrome 50 or 51 that has the first fully compatible implementation.
I completely agree with you, but doesn't make sense to have a fetch API returning something different from what I can instantiate using a call to the Promise constructor.
What can I say... If native promise implementation is incorrect - it should be replaced. Most alternative Promise polyfills do the same. Someone just replaces global Promise, for example, to Bluebird. So anyway instanceof detection for most cases makes no sense. In your code you can just wrap fetch and have expected instance:
var _fetch = fetch;
window.fetch = (...args) => Promise.resolve(_fetch(...args));
Looks nice, but not implementable. Thanks all for take time to answer :smile:.
What can I say... If native promise implementation is incorrect - it should be replaced. Most alternative
Promisepolyfills do the same. Someone just replaces globalPromise, for example, to Bluebird. So anywayinstanceofdetection for most cases makes no sense. In your code you can just wrapfetchand have expected instance:var _fetch = fetch; window.fetch = (...args) => Promise.resolve(_fetch(...args));
I had to also wrap the Promise-lookalike returned by .json() in MS Edge (15/16/17), in order to be able to use .finally() on its parsed response:
fetch(url)
.then(response => {
let nativeFetchThenable = response.json();
// In MS Edge, fetch().json() returns a non-Promise thenable, which cannot be polyfilled with .finally().
// Therefore, we wrap the thenable by resolving a new (polyfilled) Promise with it,
// so we can call .finally() on the Promise:
let wrappedFetchPromise = Promise.resolve(nativeFetchThenable);
wrappedFetchPromise.then(data => myLocalData = data).finally(() => {
doSomething(myLocalData);
}
);
})
.catch(error => {
myLocalData = [];
console && console.error(error);
});
What can I say... If native promise implementation is incorrect - it should be replaced.
It is correct enough for some applications.
This issue is really annoying. Promise#finally polyfills do not work in case core-js is used.
Is there a way to replace fetch conditionally? Seems, no.
@Yaffle No-one has shown an example of what is actually not working, so if you have one, it would be more helpful to have an example to discuss.
@loganfsmyth https://github.com/Yaffle/EventSource/issues/118
in short: I need to have "Promise#finally", I have a polyfill for it. I am using fetch(url).finally(...).
I added a workaround which should fix a big part of cases by patching .than and adding .finally on / to native Promise prototype.
I'm having this issue also on Microsoft Edge version 44.17763.831.0 and Firefox version 68.12.0esr (32-bit).
I'm using 'defaults' for targeting browserlists and the following:
my webpack config is the following:
const baseConfig = {
entry: {
app: [INDEX_JS_PATH]
},
resolve: {
extensions: ['.js'],
modules: [NODE_MODULES]
},
output: {
path: DIST_PATH,
filename: path.join('shell', 'static', '[name]-[hash].js'),
chunkFilename: path.join('shell', 'static', '[name].[hash].js'),
publicPath: '/'
},
plugins: [
// Clean up "/dist" between each build
new CleanWebpackPlugin(),
// Creates CSS sheets
new MiniCssExtractPlugin({
filename: path.join('shell', 'static', 'app.[hash].css'),
chunkFilename: '[id].css'
}),
// Creates "index.html" into "/dist"
new HtmlWebpackPlugin({
filename: `./${packageId}/index.html`,
template: path.resolve(cwd, './src/index.html')
})
],
module: {
rules: [
{
test: /\.js$/,
include: [SRC_PATH],
use: [
{
loader: require.resolve('babel-loader'),
options: {
babelrc: false,
cacheDirectory: true,
// Plugins run before presets from first to last
plugins: [
require.resolve('babel-plugin-styled-components'),
require.resolve('@babel/plugin-proposal-class-properties')
],
// Presets runtime ordering is reversed
presets: [
[
require.resolve('@babel/preset-env'),
{
// https://github.com/zloirock/core-js/blob/master/docs/2019-03-19-core-js-3-babel-and-a-look-into-the-future.md
useBuiltIns: 'usage',
corejs: '3.6',
targets: 'defaults'
}
],
[
require.resolve('@babel/preset-react'),
{
development: process.env.BABEL_ENV === 'development'
}
]
]
}
}
]
},
{
test: /\.css$/i,
use: [
{
loader: MiniCssExtractPlugin.loader,
options: {
hmr: process.env.NODE_ENV === 'development'
}
},
'css-loader'
]
},
{
test: /\.(png|jpg|gif|svg|eot|ttf|woff|woff2)$/i,
loader: 'file-loader',
options: {
outputPath: path.join('shell', 'static'),
name: '[path][name].[ext]'
}
}
]
}
};
I'm going crazy
Most helpful comment
What can I say... If native promise implementation is incorrect - it should be replaced. Most alternative
Promisepolyfills do the same. Someone just replaces globalPromise, for example, to Bluebird. So anywayinstanceofdetection for most cases makes no sense. In your code you can just wrapfetchand have expected instance: