【问题标题】:how to call another async function after the first one completes?第一个完成后如何调用另一个异步函数?
【发布时间】:2021-07-26 18:51:51
【问题描述】:

我刚刚开始了解 Javascript 承诺的工作原理。我理解这些概念和一些代码。但是在下面的 sn-p 中,我没有看到“then()”或“catch()”,所以我不太确定如何修改它,以便在成功时调用另一个异步方法。

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);
        });
      }
    }
  },
});

当此代码循环并复制/上传应用程序时,我想使用此代码部署相同的应用程序:

  return sppkgDeploy.deploy({
    username: uname, 
    password: pswd,
    absoluteUrl: catURL
    filename: filename,
    skipFeatureDeployment: false,
    verbose: true
  });

你能指出我如何“链接”它的正确方向吗?现在我正在尝试看看是否可以在 .on 之后添加一个 .then。

编辑 1

我尝试像这样更改内部 for 循环:

        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

它会报错:

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

所以我添加了一个 try/catch,但我从来没有最终陷入困境。 这是当前代码的样子:

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');
    }

【问题讨论】:

  • await 完全按照它的建议行事:它“暂停”执行,直到以下 Promise 解决。

标签: javascript asynchronous sharepoint promise


【解决方案1】:

编辑 1: 我认为流 (pipe) 部分存在一些错误,因此在该部分添加了错误处理,从您的日志中我看到至少有 1 个应用程序已成功发布,所以我相信 reject 部分将允许你检查进一步的错误。 UnhandledPromiseRejectionWarning 应该与 reject 部分一起修复。

        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

我会使用await 来执行此操作,因为您位于标记为async 的块内,而不是使用then/catch。当您调用await 时,您只会在该await 代码解析时执行下一行代码,或者如果它拒绝它会转到catch 块,如下所示:


    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);
        }
      },
    });

请注意,由于您使用的是await new Promise(...),因此sppkgDeploy.deploy(...) 将是最后执行的操作。如果await new Promise(...) 抛出错误,您将遇到catch 块而不运行要部署的代码

【讨论】:

  • 感谢您。但是......我需要 for 循环内的 sppkgDeploy 逻辑。所以......每个应用程序都被上传,然后部署......然后循环到下一个应用程序。
  • 编辑了答案,请告诉我你现在遇到了什么错误:)
  • 部署逻辑需要在每个站点发生。 Aka 在 BOTH for 循环中。
  • 我仔细检查了括号,您的部署逻辑肯定在第二个 for 循环之外。不过没关系。我刚把它搬进去。我添加了 on('error) 并重新测试了,但仍然收到有关未处理的承诺拒绝的错误。你的例子帮助我理解了语法和结构,所以我现在会继续搜索其他例子。
  • 好吧,至少它在某种程度上有所帮助:)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-03-03
  • 1970-01-01
  • 2021-11-01
  • 2018-07-10
  • 1970-01-01
  • 2019-10-04
相关资源
最近更新 更多