https请求循环,在发出最后一个请求后调用函数节点

时间:2018-10-08 15:22:20

标签: javascript node.js

假设我多次调用https来检索数据,并且我想在最后一个请求的末尾调用函数formatJsonToLocale。除了检查数组的最后一个元素外,是否有办法确定该请求何时结束。

let sheetsArray = []

function sheetsAsJsonById (ids) {
  for (let i = 0; i < ids.length; i++) {
    const queryUrl = `sheets.html`

    https
      .get(queryUrl, res => {
        let stream = []
        res
      .on('data', function (data) {
        stream.push(data)
      })
      .on('end', function () {
        let data = Buffer.concat(stream)

        data = JSON.parse(data)
        sheetArrays.push(data['values'])

        formatJsonToLocale(sheetsArray) // <----- call this one after last request
      })
  })
  .on('error', err => {
    console.error(`Error in response: ${err}`)
  })
 }
}

当我在函数外部调用formatJsonToLocale时,我会遇到一个问题,即前一个函数可能无法完成,因为https会异步处理内容。

关于如何处理此问题的任何建议?

2 个答案:

答案 0 :(得分:1)

您需要跟踪在for循环中执行的异步代码(https.get)的执行情况。这可以通过如下的诺言来实现:

let sheetsArray = []

function sheetsAsJsonById (ids) {

    let promises = []

    for (let i = 0; i < ids.length; i++) {
        const queryUrl = `sheets.html`
        promises.push(makeHTTPRequest(queryUrl))
    }

    Promise.all(promises).then((sheetArrays) => {
        formatJsonToLocale(sheetsArray)
    })
}



const makeHTTPRequest = (url) => {
    return new Promise((resolve, reject) => {
        https
          .get(url, res => {
            let stream = []
            res
          .on('data', function (data) {
            stream.push(data)
          })
          .on('end', function () {
            let data = Buffer.concat(stream)

            data = JSON.parse(data)
            resolve(data)
          })
          .on('error', err => {
            console.error(`Error in response: ${err}`)
          })
    })
}

如果要坚持使用回调,可以使用async节点模块的async.each函数。

答案 1 :(得分:0)

import UIKit import AVFoundation import ImageDetect class ViewController: UIViewController,UIImagePickerControllerDelegate,UINavigationControllerDelegate { @IBOutlet weak var cameraView: UIView! @IBOutlet weak var imgvew: UIImageView! private var scanTimer: Timer? var captureSession = AVCaptureSession() var sessionOutput = AVCaptureStillImageOutput() var previewLayer = AVCaptureVideoPreviewLayer() var isBackCamera = true var clickedImage: Data? var captureDevice : AVCaptureDevice? var imagePicker : UIImagePickerController! override func viewDidLoad() { } override func viewWillAppear(_ animated: Bool) { if AVCaptureDevice.authorizationStatus(for: AVMediaType.video) == AVAuthorizationStatus.authorized { self.camera() } else { AVCaptureDevice.requestAccess(for: AVMediaType.video, completionHandler: { (granted :Bool) -> Void in if granted == true { DispatchQueue.main.async { self.camera() } } else { // self.showPermistionAlert() } }) } // camera() scanTimer = Timer.scheduledTimer(timeInterval: 1.0, target: self, selector: #selector(getImages), userInfo: nil, repeats: true) } func camera(){ self.tabBarController?.tabBar.isHidden = true let devices = AVCaptureDevice.devices(for: AVMediaType.video) for device in devices{ do{ let camera = getDevice(position: .front) let input = try AVCaptureDeviceInput(device: camera!) if captureSession.canAddInput(input){ captureSession.addInput(input) sessionOutput.outputSettings = [AVVideoCodecKey: AVVideoCodecJPEG] if captureSession.canAddOutput(sessionOutput){ captureSession.startRunning() captureSession.addOutput(sessionOutput) previewLayer = AVCaptureVideoPreviewLayer(session: captureSession) previewLayer.videoGravity = AVLayerVideoGravity.resizeAspectFill previewLayer.connection?.videoOrientation = AVCaptureVideoOrientation.portrait cameraView.layer.addSublayer(previewLayer) previewLayer.position = CGPoint(x: self.cameraView.frame.width/2, y: self.cameraView.frame.height/2) cameraView.contentMode = .scaleToFill previewLayer.bounds = cameraView.frame } } } catch{ print("error") } } } @objc func getImages() { if let videoConnection = sessionOutput.connection(with: AVMediaType.video) { sessionOutput.captureStillImageAsynchronously(from: videoConnection, completionHandler: {buffer, error in let imageData = AVCaptureStillImageOutput.jpegStillImageNSDataRepresentation(buffer!) let captureimage = UIImage(data: imageData!)! self.imgvew.image = captureimage captureimage.detector.crop(type: .face) { result in print(result) switch result { case .success(let faces): print("Success") case .notFound: print("Notfound") case .failure(let error): print("Failure") } } }) } } func getDevice(position: AVCaptureDevice.Position) -> AVCaptureDevice? { let devices: NSArray = AVCaptureDevice.devices() as NSArray; for de in devices { let deviceConverted = de as! AVCaptureDevice if(deviceConverted.position == position){ return deviceConverted } } return nil } } 包装在Promise中,它会解决https.get事件,并拒绝出现任何错误。现在您可以等待promise,并且在for循环完成后调用函数

end