Reputation: 15660
I'm just started to learn about how Javascript promises work. I understand the concepts, and some code. But in the snippet below, i don't see the "then()" or "catch()" so I'm not too sure how to modify it so that when it's successful, i call another async method.
const gulp = require('gulp');
const build = require('@microsoft/sp-build-web');
const spsync = require('gulp-spsync-creds').sync;
const sppkgDeploy = require('node-sppkg-deploy');
build.task("deploySharepointApps", {
execute: async () => {
const appList = require("./config/apps.json");
if (!pluginList) {
return;
}
for (const { name, sites } of appList.apps) {
const folderLocation = `./apps/${name}`;
for (const site of sites) {
await new Promise((resolve) => {
gulp
.src(folderLocation)
.pipe(
spsync({
username: creds.username,
password: creds.password,
site: coreOptions.siteUrl + site,
libraryPath: coreOptions.appCatalog,
publish: true,
})
)
.on("finish", resolve);
});
}
}
},
});
As this code loops and copies / uploads an app, I want to then deploy the same application using this code:
return sppkgDeploy.deploy({
username: uname,
password: pswd,
absoluteUrl: catURL
filename: filename,
skipFeatureDeployment: false,
verbose: true
});
Can you point me in the right direction on how to "chain" this? Right now I'm experimenting to see if i can add a .then right after the .on.
EDIT 1
I tried to change the inner for loop like this:
for (const site of sites) {
// Here await each gulp pipeline to finish before moving on to the next.
await new Promise((resolve) => {
gulp
.src(folderLocation)
.pipe(
spsync({
username: uname,
password: pswd,
site: coreOptions.siteUrl + site,
libraryPath: coreOptions.appCatalog,
publish: true,
})
)
.on("finish", resolve);
});
await sppkgDeploy.deploy({
username: uname,
password: pswd,
absoluteUrl: catURL,
filename: name,
skipFeatureDeployment: false,
verbose: true,
});
}//end for
It bombs with an error:
dev3:spfx-plugins admin$ gulp upload-sequential
Build target: DEBUG
[16:00:41] Using gulpfile /src/spfx-plugins/gulpfile.js
[16:00:41] Starting gulp
[16:00:41] Starting 'upload-sequential'...
[16:00:41] Uploading test.sppkg
[16:00:42] Upload successful 1679ms
[16:00:43] Published file 403ms
(node:69005) UnhandledPromiseRejectionWarning: Failed to call the API URL: https://<mydomain>.sharepoint.com/sites/<mysite>/AppCatalog/_api/site?$select=Id
(node:69005) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). (rejection id: 1)
(node:69005) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.
About to exit with code: 0
Process terminated before summary could be written, possible error in async code not continuing!
Trying to exit with exit code 1
So I wrapped added a try/catch but I never end up in the catch. Here's what the current code looks like:
build.task("deploySharepointApps", {
execute: async () => {
try
{
const appList = require("./config/apps.json");
for (const { name, sites } of pluginList.plugins) {
for (const site of sites) {
[original code]
await sppkgDeploy.deploy({
username: uname,
password: pswd,
absoluteUrl: catURL,
filename: name,
skipFeatureDeployment: false,
verbose: true,
});
} // end for
} //end for
} catch (error) {
console.log('inside the error handler');
}
Upvotes: 2
Views: 387
Reputation: 863
Edit 1:
I think there is some error on the stream (pipe
) part, so added error handling on that part, from your log i see that at least 1 app has been published with success, so i believe the reject
part will allow you to check further errors. The UnhandledPromiseRejectionWarning
should been fixed with that reject
part.
for (const site of sites) {
// Here await each gulp pipeline to finish before moving on to the next.
await new Promise((resolve, reject) => {
gulp
.src(folderLocation)
.pipe(
spsync({
username: uname,
password: pswd,
site: coreOptions.siteUrl + site,
libraryPath: coreOptions.appCatalog,
publish: true,
})
)
.on('error',
(error) => {
console.log('spsync error:', error);
reject(error);
})
.on("finish", resolve());
});
await sppkgDeploy.deploy({
username: uname,
password: pswd,
absoluteUrl: catURL,
filename: name,
skipFeatureDeployment: false,
verbose: true,
});
}//end for
I would do it using await
since you're inside a block marked as async
, and not using the then/catch
. When you call await
you're only executing the next line of code when that await
code resolves, or if it rejects it goes to the catch
block as in below:
const gulp = require("gulp");
const build = require("@microsoft/sp-build-web");
const spsync = require("gulp-spsync-creds").sync;
const sppkgDeploy = require("node-sppkg-deploy");
build.task("deploySharepointApps", {
execute: async () => {
const appList = require("./config/apps.json");
if (!pluginList) {
return;
}
try {
for (const { name, sites } of appList.apps) {
const folderLocation = `./apps/${name}`;
for (const site of sites) {
await new Promise((resolve) => {
gulp
.src(folderLocation)
.pipe(
spsync({
username: creds.username,
password: creds.password,
site: coreOptions.siteUrl + site,
libraryPath: coreOptions.appCatalog,
publish: true,
})
) // Notice the resolve() here
.on("finish", resolve());
});
}
}
await sppkgDeploy.deploy({
username: uname,
password: pswd,
absoluteUrl: catURL,
filename: filename,
skipFeatureDeployment: false,
verbose: true,
});
} catch (error) {
console.log(err);
}
},
});
Notice that since you're using await new Promise(...)
, the sppkgDeploy.deploy(...)
will be the last thing to be executed. And if await new Promise(...)
throws an error, you'll be hitting the catch
block and not running the code to deploy
Upvotes: 1