【问题标题】:javascript: how to make multiple async calls in a loopjavascript:如何在循环中进行多个异步调用
【发布时间】:2021-07-23 19:36:41
【问题描述】:

我的 gulpfile.js 中有以下任务:

'use strict';

const gulp = require('gulp');
const build = require('@microsoft/sp-build-web');
const spsync = require('gulp-spsync-creds').sync;
const sppkgDeploy = require('node-sppkg-deploy');

const config = require('./dev-config.json');
var coreOptions = {
        siteUrl: config.coreOptions.siteUrl,
        appCatalog: config.coreOptions.appCatalog
    };
var creds = {
        username: config.creds.username,
        password: config.creds.password
    };

build.task('upload-single-app', {
  execute: (config) => {
      return new Promise((resolve, reject) => {
          const pluginList = require('./config/plugin-deployment.json');
          if (pluginList)
          {
            for (let i = 0; i < pluginList.plugins.length; i++) {
                  const folderLocation = `./plugins/` + pluginList.plugins[i].name;
                  for (let x = 0; x < pluginList.plugins[i].sites.length; x++) {

                        console.log(pluginList.plugins[i].sites[x]);
                        return gulp.src(folderLocation)
                        .pipe(spsync({
                            "username": creds.username,
                            "password": creds.password,
                            "site": coreOptions.siteUrl + pluginList.plugins[i].sites[x],
                            "libraryPath": coreOptions.appCatalog,
                            "publish": true
                        }))
                        .on('finish', resolve);
                      }//end inner for
              }// end for
          } else {
            console.log("Plugin list is empty");
          }
        });
  }
});

这是驱动这个的 JSON 数据:

{
  "plugins":
  [
    {
      "name": "Bluebeam.OpenRevuExtension.sppkg",
      "description":"some description",
      "version":"20.2.30.5",
      "sites":["sp_site1","sp_site2"]
    }
  ]
}

当我运行此代码时,它成功地将包部署到站点 1,但不是站点 2。没有错误。这是输出的样子:

devbox:plugintest admin$ gulp upload-single-app
Build target: DEBUG
[14:51:48] Using gulpfile /src/plugintest/gulpfile.js
[14:51:48] Starting gulp
[14:51:48] Starting 'upload-single-app'...
sp_site1
[14:51:48] Uploading Bluebeam.OpenRevuExtension.sppkg
[14:51:50] Upload successful 1919ms
[14:51:51] Published file 982ms
[14:51:51] Finished 'upload-single-app' after 2.92 s
[14:51:51] ==================[ Finished ]==================
[14:51:52] Project plugintest version:1.0.0
[14:51:52] Build tools version:3.12.1
[14:51:52] Node version:v10.24.1
[14:51:52] Total duration:6.48 s

我对 JS 中的异步编码不是很熟悉,但我想也许我会重构,所以我有 2 个单独的任务。 一个人将有循环遍历 JSON 数据的逻辑......并且对于每个它将调用一个单独的构建任务。像这样的东西:(伪代码)

build.task('main', {
     for each plugin in json file {
         for each site I need to deploy to {
             call build.task('upload_app');
             call build.task('deploy_app');
         }
     }
  });

问题

这是一个好方法吗?你能给我一些关于如何做到这一点的指示吗?

谢谢。

【问题讨论】:

  • 这取决于你需要什么。您是否需要等待每个站点部署完毕,然后再转到下一个站点并逐个(按顺序)浏览它们?或者您想一次性部署它们并在它们全部完成时完成 gulp 任务(并行)?
  • @EmielZuurbier 我认为并行是可以的,只要我有办法从每次尝试中捕获结果

标签: javascript sharepoint gulp


【解决方案1】:

您当前的行为发生是因为您有一个 Promise,它通过在第一个站点完成时调用 resolve 在循环的第一次迭代中解析。

按顺序

相反,您应该在第二个循环中为每个站点设置一个 Promise。结合async / await 语法,等待循环中的每个Promise 解决,然后再继续下一个。

build.task("upload-single-app", {
  execute: async () => {
    const pluginList = require("./config/plugin-deployment.json");

    if (!pluginList) {
      return;
    }
    
    for (const { name, sites } of pluginList.plugins) {
      const folderLocation = `./plugins/${name}`;

      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: creds.username,
                password: creds.password,
                site: coreOptions.siteUrl + site,
                libraryPath: coreOptions.appCatalog,
                publish: true,
              })
            )
            .on("finish", resolve);
        });
      }
    }
  },
});

并行

您还可以遍历每个站点并使用数组的map 方法返回一个Promise。然后将所有 Promise 收集到一个数组中,并使用 Promise.all() 等待所有 Promise 都实现。

build.task("upload-single-app", {
  execute: async () => {
    const pluginList = require("./config/plugin-deployment.json");

    if (!pluginList) {
      return;
    }
    
    const pluginBuilds = await Promise.all(pluginList.plugins.flatMap(({ name, sites }) => {
      const folderLocation = `./plugins/${name}`;

      return sites.map(site => 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 pluginBuilds;
  },
});

【讨论】:

  • 'pluginList.plugins.flatMap is not a function' 是我在尝试并行示例时得到的结果。
猜你喜欢
  • 2019-01-29
  • 2023-03-29
  • 1970-01-01
  • 2021-12-12
  • 2018-08-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-12-26
相关资源
最近更新 更多