TypeScript中异步/等待和Promise的工作方式

时间:2019-07-04 07:39:15

标签: typescript async-await

我有一个小函数来学习异步,等待和承诺在这里的工作方式。

function delay(ms: number) {
    return new Promise<void>(function(resolve) {
       setTimeout(resolve, ms);
    });
}

async function asyncAwait() {
    console.log("A");

    await delay(1000);
    console.log("B");

    await delay(1000);
    console.log("C");
}

asyncAwait();
console.log("D");

我的理解是,工作流程就像

首先呼叫asyncAwait();,然后打印A,然后等待1并打印B,然后再等待1并打印C,最后打印D

但是我的输出就像

A
D
B
C

我不知道为什么console.log("D")显示第二。

任何人都可以解释上面的代码吗?

预先感谢

3 个答案:

答案 0 :(得分:2)

您必须await进行asyncAwait()通话:


function delay(ms: number) {
    return new Promise<void>(function(resolve) {
       setTimeout(resolve, ms);
    });
}

async function asyncAwait() {
    console.log("A");

    await delay(1000);
    console.log("B");

    await delay(1000);
    console.log("C");
}

async function main() {
    await asyncAwait();
    console.log("D");
}

main();

答案 1 :(得分:1)

之所以这样,是因为在后台,您的代码是这样的:

function equivalentFunction() {
    console.log("A");
    setTimeout(
        function() {
            console.log("B");
            setTimeout(
                function() {
                    console.log("C");
                }
            ,1000)
        }
    ,1000)
}

equivalentFunction();
console.log("D");

答案 2 :(得分:1)

这是异步调用的工作方式。

您认为代码执行是什么样的:

override fun onCreate(savedInstanceState: Bundle?) {
.
.
.
  val buildCode = BuildConfig.VERSION_CODE
  // Creates instance of the manager.
  val appUpdateManager = AppUpdateManagerFactory.create(ctx)

  appUpdateManager.registerListener(this)

  Log.i(TAG, "IMMEDIATE Application context = $ctx")

  // Returns an intent object that you use to check for an update.
  val appUpdateInfoTask = appUpdateManager.appUpdateInfo

  Log.i(TAG, "IMMEDIATE Application Update - start listening for updates")
  // Checks that the platform will allow the specified type of update.
  appUpdateInfoTask.addOnSuccessListener { appUpdateInfo ->

      Log.i(TAG, "IMMEDIATE Application addOnSuccessListener returned appUpdateInfo.updateAvailability() = ${appUpdateInfo.updateAvailability()}")
      Log.i(TAG, "IMMEDIATE Application addOnSuccessListener  IMMEDIATE appUpdateInfo.isUpdateTypeAllowed = ${appUpdateInfo.isUpdateTypeAllowed(AppUpdateType.IMMEDIATE)}")
      Log.i(TAG, "IMMEDIATE Application addOnSuccessListener  FLEXIBLE appUpdateInfo.isUpdateTypeAllowed = ${appUpdateInfo.isUpdateTypeAllowed(AppUpdateType.FLEXIBLE)}")
      Log.i(TAG, "IMMEDIATE Application addOnSuccessListener  appUpdateInfo.availableVersionCode() = ${appUpdateInfo.availableVersionCode()}")
      Log.i(TAG, "IMMEDIATE Application addOnSuccessListener  appUpdateInfo.packageName() = ${appUpdateInfo.packageName()}")
      Log.i(TAG, "IMMEDIATE Application addOnSuccessListener  appUpdateInfo.installStatus() = ${appUpdateInfo.installStatus()}")

      if (appUpdateInfo.updateAvailability() == UpdateAvailability.UPDATE_AVAILABLE && appUpdateInfo.isUpdateTypeAllowed(AppUpdateType.IMMEDIATE)) {
          Log.i(TAG, "IMMEDIATE Application Update is available. Version = ${appUpdateInfo.availableVersionCode()}  Start the update flow")
          appUpdateManager.startUpdateFlowForResult(
              appUpdateInfo,
              AppUpdateType.IMMEDIATE,
              view as MainActivity,
              APPLICATION_UPDATE_REQUEST_CODE
          )
      }else {
          Log.e(TAG, "Update not available")
      }
  }
}


override fun onStateUpdate(installState: InstallState) {
    if (installState.installStatus() == InstallStatus.DOWNLOADED) {
        Log.i(TAG, "Application update. download complete")
    }
}


  override fun onResume() {
    .
    .
    .
      resumeApplicationUpdateIfNeeded()
   }

  private fun resumeApplicationUpdateIfNeeded() {
       appUpdateManager.appUpdateInfo?.addOnSuccessListener { appUpdateInfo ->
           if (appUpdateInfo.updateAvailability() == UpdateAvailability.DEVELOPER_TRIGGERED_UPDATE_IN_PROGRESS) {
               if (appUpdateInfo.isUpdateTypeAllowed(AppUpdateType.IMMEDIATE)) {
                   router.requestImmediateUpdate(appUpdateInfo) // calls appUpdateManager.startUpdateFlowForResult
               } else {
                   router.requestFlexibleUpdate(appUpdateInfo)
               }
           } else if (appUpdateInfo.installStatus() == InstallStatus.DOWNLOADED) {
               showApplicationUpdateSuccessSnackbar()
           }
       }
  }

然后在该函数内部:

function delay(ms: number) {
    return new Promise<void>(function(resolve) {
       setTimeout(resolve, ms);
    });
}

async function asyncAwait() {
    console.log("A");

    await delay(1000);
    console.log("B");

    await delay(1000);
    console.log("C");
}

asyncAwait();   // <-- 1st call
console.log("D");

然后最后

async function asyncAwait() {
    console.log("A");  // <--- 1st print, as it is synchronous

    await delay(1000); // <--- await
    console.log("B");  // <--- 2nd print

    await delay(1000); // <-- await
    console.log("C");  // <-- 3rd print
}

但是,异步功能是异步的。因此,所有异步调用都进入队列,并在以后进行处理。

因此,首先执行同步调用:

function delay(ms: number) {
    return new Promise<void>(function(resolve) {
       setTimeout(resolve, ms);
    });
}

async function asyncAwait() {
    console.log("A");

    await delay(1000);
    console.log("B");

    await delay(1000);
    console.log("C");
}

asyncAwait();
console.log("D"); // <-- last print

然后是异步调用。

console.log("A"); console.log("D"); 仅在await函数中起作用。

所以功能:

async

大致等于:

async function asyncFunc() {
  console.log("A");

  await delay(1000);
  console.log("B");
}

因此,如果要在异步功能之后执行console.log(“ D”),则应等待asyncFunction。但是要使用await,您必须具有异步功能:

asyncFunc() {
  console.log('A');
  delay().then(()=> {
     console.log('B');
  });
}