Javascript 如何创建包含画布元素的承诺

Javascript 如何创建包含画布元素的承诺,javascript,canvas,promise,q,Javascript,Canvas,Promise,Q,我在将缩略图生成功能转换为承诺时遇到一些问题 我需要让它运行承诺。一旦生成缩略图,当前拇指是未定义的(这是有意义的,因为它需要先生成) 我不理解img.onload的第一部分,我的工作是将其设置为$scope,我知道这是一种传递数据的糟糕方式 var img = new Image; img.onload = resizeImage; img.src = $scope.imageData; function resizeImage() { var n

我在将缩略图生成功能转换为承诺时遇到一些问题

我需要让它运行承诺。一旦生成缩略图,当前拇指是未定义的(这是有意义的,因为它需要先生成)

我不理解img.onload的第一部分,我的工作是将其设置为$scope,我知道这是一种传递数据的糟糕方式

    var img = new Image;
    img.onload = resizeImage;
    img.src = $scope.imageData;

    function resizeImage() {
      var newDataUri = imageToDataUri(this, 100, 100);
      $scope.imageDataThumb = newDataUri;
      $scope.$apply();
    }
    function imageToDataUri(img, width, height) {
      // create an off-screen canvas
      var canvas = document.createElement('canvas'),
      ctx = canvas.getContext('2d');
      canvas.width = width;
      canvas.height = height;
      ctx.drawImage(img, 0, 0, width, height);
      var quality = 1.0;
      return canvas.toDataURL('image/jpeg', quality).split(",")[1];  // quality = [0.0, 1.0]
    }

    var imgGuid = factory.guid();

    //Save the image to storage
    console.log($scope.imageDataThumb);
    Promise.all([fireBaseService.postImageToStorage(imageData, "images", imgGuid), fireBaseService.postImageToStorage($scope.imageDataThumb, "images", "thumb_" + imgGuid)])
      .then(function (results) {
      //do stuff with results
      });
我需要让它运行承诺。一旦生成缩略图

画布中的任何图像导出函数都不会返回承诺:

toDataURL()
DOMString=canvas.toDataURL(类型,编码选项);//同步的

void canvas.toBlob(回调、mimeType、qualityArgument);//异步的

唯一的方法是手动将函数包装到承诺中(尽管对于同步函数,如
toDataURL()
,这没有什么意义。如果只生成缩略图,我建议将运动图像加载到承诺中,因为图像加载是异步的,所以这样做更有意义):

现在,您可以将通话作为任何承诺:

var promise = imageToDataUri(img, width, height);
promise.then(function(str) { ... });


还有一个小注意:通过将头与数据URI分离,它不再是数据URL,只是一个BASE-64编码的字符串——函数名称需要考虑的东西。

看起来你的代码被剪除了。Hi @ McSkuluthISS——这只是服务调用的开始来保存缩略图图像,@Bergi是正确的:您的问题是由您的部件的简单异步错误处理引起的。事实上,这和我们的核心问题是一样的。如果接受的答案似乎对你有效,那只是因为你尝试加载的图像不到4毫秒。你将面临同样的问题,更大的图像。您应该从这个答案中选择的唯一一句话是“我也建议将运动图像加载到promise中”。
imageToDataUri
不是问题所在,应该保持同步。(如果您愿意,您仍然可以执行
Promise.delay(4)。然后(imageToDataUri)
以获得与答案中的代码相同的效果)。问题是OP正在调用
resizeImage
作为其映像的
onload
处理程序,但没有等待。
function imageToDataUri(img, width, height) {
  return new Promise(function(success, reject) {
    // create an off-screen canvas
    var ctx = document.createElement('canvas').getContext("2d");
    ctx.canvas.width = width;
    ctx.canvas.height = height;
    ctx.drawImage(img, 0, 0, width, height);
    var quality = 1.0;
    setTimeout(function() {
      success(canvas.toDataURL('image/jpeg', quality).split(",")[1]);  //quality=[0.0,1.0]
    }, 4);  // make call async
  })
}
var promise = imageToDataUri(img, width, height);
promise.then(function(str) { ... });
Promise.all([promise, promise2, ...])
  .then( ... );